/*
 *
 *    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 |
| BasicInformation                                                    | 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 |
| BridgedDeviceBasicInformation                                       | 0x0039 |
| Switch                                                              | 0x003B |
| AdministratorCommissioning                                          | 0x003C |
| OperationalCredentials                                              | 0x003E |
| GroupKeyManagement                                                  | 0x003F |
| FixedLabel                                                          | 0x0040 |
| UserLabel                                                           | 0x0041 |
| ProxyConfiguration                                                  | 0x0042 |
| ProxyDiscovery                                                      | 0x0043 |
| ProxyValid                                                          | 0x0044 |
| BooleanState                                                        | 0x0045 |
| IcdManagement                                                       | 0x0046 |
| ModeSelect                                                          | 0x0050 |
| TemperatureControl                                                  | 0x0056 |
| RefrigeratorAlarm                                                   | 0x0057 |
| AirQuality                                                          | 0x005B |
| SmokeCoAlarm                                                        | 0x005C |
| HepaFilterMonitoring                                                | 0x0071 |
| ActivatedCarbonFilterMonitoring                                     | 0x0072 |
| CeramicFilterMonitoring                                             | 0x0073 |
| ElectrostaticFilterMonitoring                                       | 0x0074 |
| UvFilterMonitoring                                                  | 0x0075 |
| IonizingFilterMonitoring                                            | 0x0076 |
| ZeoliteFilterMonitoring                                             | 0x0077 |
| OzoneFilterMonitoring                                               | 0x0078 |
| WaterTankMonitoring                                                 | 0x0079 |
| FuelTankMonitoring                                                  | 0x007A |
| InkCartridgeMonitoring                                              | 0x007B |
| TonerCartridgeMonitoring                                            | 0x007C |
| 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 |
| UnitTesting                                                         | 0xFFF1FC05|
| FaultInjection                                                      | 0xFFF1FC06|
\*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*\
| Cluster Identify                                                    | 0x0003 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * Identify                                                          |   0x00 |
| * TriggerEffect                                                     |   0x40 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * IdentifyTime                                                      | 0x0000 |
| * IdentifyType                                                      | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadIdentifyEventList : public ReadAttribute {
public:
    ReadIdentifyEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadIdentifyEventList() {}

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

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

class SubscribeAttributeIdentifyEventList : public SubscribeAttribute {
public:
    SubscribeAttributeIdentifyEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeIdentifyEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Identify.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadGroupsEventList : public ReadAttribute {
public:
    ReadGroupsEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadGroupsEventList() {}

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

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

class SubscribeAttributeGroupsEventList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupsEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeGroupsEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Groups.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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("GroupIdentifierFrom", 0, UINT16_MAX, &mRequest.groupIdentifierFrom);
        AddArgument("SceneIdentifierFrom", 0, UINT8_MAX, &mRequest.sceneIdentifierFrom);
        AddArgument("GroupIdentifierTo", 0, UINT16_MAX, &mRequest.groupIdentifierTo);
        AddArgument("SceneIdentifierTo", 0, UINT8_MAX, &mRequest.sceneIdentifierTo);
        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);
        __auto_type * 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.groupIdentifierFrom = [NSNumber numberWithUnsignedShort:mRequest.groupIdentifierFrom];
        params.sceneIdentifierFrom = [NSNumber numberWithUnsignedChar:mRequest.sceneIdentifierFrom];
        params.groupIdentifierTo = [NSNumber numberWithUnsignedShort:mRequest.groupIdentifierTo];
        params.sceneIdentifierTo = [NSNumber numberWithUnsignedChar:mRequest.sceneIdentifierTo];
        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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadScenesEventList : public ReadAttribute {
public:
    ReadScenesEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadScenesEventList() {}

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

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

class SubscribeAttributeScenesEventList : public SubscribeAttribute {
public:
    SubscribeAttributeScenesEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeScenesEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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("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 (0x00000006) command (0x00000040) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * 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.effectIdentifier = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.effectIdentifier)];
        params.effectVariant = [NSNumber numberWithUnsignedChar: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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadOnOffEventList : public ReadAttribute {
public:
    ReadOnOffEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadOnOffEventList() {}

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

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

class SubscribeAttributeOnOffEventList : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeOnOffEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadOnOffSwitchConfigurationEventList : public ReadAttribute {
public:
    ReadOnOffSwitchConfigurationEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadOnOffSwitchConfigurationEventList() {}

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

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

class SubscribeAttributeOnOffSwitchConfigurationEventList : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffSwitchConfigurationEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeOnOffSwitchConfigurationEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOffSwitchConfiguration.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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.Raw()];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride.Raw()];
        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);
        __auto_type * 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.Raw()];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride.Raw()];
        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);
        __auto_type * 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.Raw()];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride.Raw()];
        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);
        __auto_type * 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.Raw()];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride.Raw()];
        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);
        __auto_type * 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.Raw()];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride.Raw()];
        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);
        __auto_type * 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.Raw()];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride.Raw()];
        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);
        __auto_type * 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.Raw()];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride.Raw()];
        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);
        __auto_type * 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.Raw()];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride.Raw()];
        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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadLevelControlEventList : public ReadAttribute {
public:
    ReadLevelControlEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadLevelControlEventList() {}

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

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

class SubscribeAttributeLevelControlEventList : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeLevelControlEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadBinaryInputBasicEventList : public ReadAttribute {
public:
    ReadBinaryInputBasicEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadBinaryInputBasicEventList() {}

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

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

class SubscribeAttributeBinaryInputBasicEventList : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeBinaryInputBasicEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadDescriptorEventList : public ReadAttribute {
public:
    ReadDescriptorEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadDescriptorEventList() {}

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

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

class SubscribeAttributeDescriptorEventList : public SubscribeAttribute {
public:
    SubscribeAttributeDescriptorEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeDescriptorEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                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);
        __auto_type * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadBindingEventList : public ReadAttribute {
public:
    ReadBindingEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadBindingEventList() {}

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

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

class SubscribeAttributeBindingEventList : public SubscribeAttribute {
public:
    SubscribeAttributeBindingEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeBindingEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Binding.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRAccessControlClusterAccessControlEntryStruct * newElement_0;
                newElement_0 = [MTRAccessControlClusterAccessControlEntryStruct 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()) {
                            MTRAccessControlClusterAccessControlTargetStruct * newElement_3;
                            newElement_3 = [MTRAccessControlClusterAccessControlTargetStruct 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::AccessControlEntryStruct::Type> mValue;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::AccessControl::Structs::AccessControlEntryStruct::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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRAccessControlClusterAccessControlExtensionStruct * newElement_0;
                newElement_0 = [MTRAccessControlClusterAccessControlExtensionStruct 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::AccessControlExtensionStruct::Type> mValue;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::AccessControl::Structs::AccessControlExtensionStruct::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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadAccessControlEventList : public ReadAttribute {
public:
    ReadAccessControlEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadAccessControlEventList() {}

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

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

class SubscribeAttributeAccessControlEventList : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeAccessControlEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadActionsEventList : public ReadAttribute {
public:
    ReadActionsEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadActionsEventList() {}

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

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

class SubscribeAttributeActionsEventList : public SubscribeAttribute {
public:
    SubscribeAttributeActionsEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeActionsEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Actions.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 BasicInformation                                            | 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 |
| * ProductAppearance                                                 | 0x0014 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StartUp                                                           | 0x0000 |
| * ShutDown                                                          | 0x0001 |
| * Leave                                                             | 0x0002 |
| * ReachableChanged                                                  | 0x0003 |
\*----------------------------------------------------------------------------*/

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

    ~ReadBasicInformationDataModelRevision() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeDataModelRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.DataModelRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation DataModelRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBasicInformationDataModelRevision() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeDataModelRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.DataModelRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorName
 */
class ReadBasicInformationVendorName : public ReadAttribute {
public:
    ReadBasicInformationVendorName()
        : ReadAttribute("vendor-name")
    {
    }

    ~ReadBasicInformationVendorName() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeVendorNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.VendorName response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation VendorName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationVendorName : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationVendorName()
        : SubscribeAttribute("vendor-name")
    {
    }

    ~SubscribeAttributeBasicInformationVendorName() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeVendorNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.VendorName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorID
 */
class ReadBasicInformationVendorID : public ReadAttribute {
public:
    ReadBasicInformationVendorID()
        : ReadAttribute("vendor-id")
    {
    }

    ~ReadBasicInformationVendorID() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeVendorIDWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.VendorID response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation VendorID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationVendorID : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationVendorID()
        : SubscribeAttribute("vendor-id")
    {
    }

    ~SubscribeAttributeBasicInformationVendorID() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeVendorIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.VendorID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductName
 */
class ReadBasicInformationProductName : public ReadAttribute {
public:
    ReadBasicInformationProductName()
        : ReadAttribute("product-name")
    {
    }

    ~ReadBasicInformationProductName() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeProductNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.ProductName response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation ProductName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationProductName : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationProductName()
        : SubscribeAttribute("product-name")
    {
    }

    ~SubscribeAttributeBasicInformationProductName() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeProductNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.ProductName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductID
 */
class ReadBasicInformationProductID : public ReadAttribute {
public:
    ReadBasicInformationProductID()
        : ReadAttribute("product-id")
    {
    }

    ~ReadBasicInformationProductID() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeProductIDWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.ProductID response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation ProductID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationProductID : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationProductID()
        : SubscribeAttribute("product-id")
    {
    }

    ~SubscribeAttributeBasicInformationProductID() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeProductIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.ProductID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NodeLabel
 */
class ReadBasicInformationNodeLabel : public ReadAttribute {
public:
    ReadBasicInformationNodeLabel()
        : ReadAttribute("node-label")
    {
    }

    ~ReadBasicInformationNodeLabel() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeNodeLabelWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.NodeLabel response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation NodeLabel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBasicInformationNodeLabel : public WriteAttribute {
public:
    WriteBasicInformationNodeLabel()
        : WriteAttribute("node-label")
    {
        AddArgument("attr-name", "node-label");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBasicInformationNodeLabel() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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("BasicInformation NodeLabel write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBasicInformationNodeLabel : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationNodeLabel()
        : SubscribeAttribute("node-label")
    {
    }

    ~SubscribeAttributeBasicInformationNodeLabel() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNodeLabelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.NodeLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Location
 */
class ReadBasicInformationLocation : public ReadAttribute {
public:
    ReadBasicInformationLocation()
        : ReadAttribute("location")
    {
    }

    ~ReadBasicInformationLocation() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeLocationWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.Location response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation Location read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~WriteBasicInformationLocation() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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("BasicInformation Location write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBasicInformationLocation : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationLocation()
        : SubscribeAttribute("location")
    {
    }

    ~SubscribeAttributeBasicInformationLocation() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeLocationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.Location response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareVersion
 */
class ReadBasicInformationHardwareVersion : public ReadAttribute {
public:
    ReadBasicInformationHardwareVersion()
        : ReadAttribute("hardware-version")
    {
    }

    ~ReadBasicInformationHardwareVersion() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeHardwareVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.HardwareVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation HardwareVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationHardwareVersion : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationHardwareVersion()
        : SubscribeAttribute("hardware-version")
    {
    }

    ~SubscribeAttributeBasicInformationHardwareVersion() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeHardwareVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.HardwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareVersionString
 */
class ReadBasicInformationHardwareVersionString : public ReadAttribute {
public:
    ReadBasicInformationHardwareVersionString()
        : ReadAttribute("hardware-version-string")
    {
    }

    ~ReadBasicInformationHardwareVersionString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeHardwareVersionStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.HardwareVersionString response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation HardwareVersionString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationHardwareVersionString : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationHardwareVersionString()
        : SubscribeAttribute("hardware-version-string")
    {
    }

    ~SubscribeAttributeBasicInformationHardwareVersionString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeHardwareVersionStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.HardwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoftwareVersion
 */
class ReadBasicInformationSoftwareVersion : public ReadAttribute {
public:
    ReadBasicInformationSoftwareVersion()
        : ReadAttribute("software-version")
    {
    }

    ~ReadBasicInformationSoftwareVersion() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeSoftwareVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.SoftwareVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation SoftwareVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationSoftwareVersion : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationSoftwareVersion()
        : SubscribeAttribute("software-version")
    {
    }

    ~SubscribeAttributeBasicInformationSoftwareVersion() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeSoftwareVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.SoftwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoftwareVersionString
 */
class ReadBasicInformationSoftwareVersionString : public ReadAttribute {
public:
    ReadBasicInformationSoftwareVersionString()
        : ReadAttribute("software-version-string")
    {
    }

    ~ReadBasicInformationSoftwareVersionString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeSoftwareVersionStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.SoftwareVersionString response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation SoftwareVersionString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationSoftwareVersionString : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationSoftwareVersionString()
        : SubscribeAttribute("software-version-string")
    {
    }

    ~SubscribeAttributeBasicInformationSoftwareVersionString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeSoftwareVersionStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.SoftwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ManufacturingDate
 */
class ReadBasicInformationManufacturingDate : public ReadAttribute {
public:
    ReadBasicInformationManufacturingDate()
        : ReadAttribute("manufacturing-date")
    {
    }

    ~ReadBasicInformationManufacturingDate() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeManufacturingDateWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.ManufacturingDate response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation ManufacturingDate read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationManufacturingDate : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationManufacturingDate()
        : SubscribeAttribute("manufacturing-date")
    {
    }

    ~SubscribeAttributeBasicInformationManufacturingDate() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeManufacturingDateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.ManufacturingDate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PartNumber
 */
class ReadBasicInformationPartNumber : public ReadAttribute {
public:
    ReadBasicInformationPartNumber()
        : ReadAttribute("part-number")
    {
    }

    ~ReadBasicInformationPartNumber() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributePartNumberWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.PartNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation PartNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationPartNumber : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationPartNumber()
        : SubscribeAttribute("part-number")
    {
    }

    ~SubscribeAttributeBasicInformationPartNumber() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributePartNumberWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.PartNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductURL
 */
class ReadBasicInformationProductURL : public ReadAttribute {
public:
    ReadBasicInformationProductURL()
        : ReadAttribute("product-url")
    {
    }

    ~ReadBasicInformationProductURL() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeProductURLWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.ProductURL response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation ProductURL read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationProductURL : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationProductURL()
        : SubscribeAttribute("product-url")
    {
    }

    ~SubscribeAttributeBasicInformationProductURL() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeProductURLWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.ProductURL response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductLabel
 */
class ReadBasicInformationProductLabel : public ReadAttribute {
public:
    ReadBasicInformationProductLabel()
        : ReadAttribute("product-label")
    {
    }

    ~ReadBasicInformationProductLabel() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeProductLabelWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.ProductLabel response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation ProductLabel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationProductLabel : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationProductLabel()
        : SubscribeAttribute("product-label")
    {
    }

    ~SubscribeAttributeBasicInformationProductLabel() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeProductLabelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.ProductLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SerialNumber
 */
class ReadBasicInformationSerialNumber : public ReadAttribute {
public:
    ReadBasicInformationSerialNumber()
        : ReadAttribute("serial-number")
    {
    }

    ~ReadBasicInformationSerialNumber() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeSerialNumberWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.SerialNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation SerialNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationSerialNumber : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationSerialNumber()
        : SubscribeAttribute("serial-number")
    {
    }

    ~SubscribeAttributeBasicInformationSerialNumber() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeSerialNumberWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.SerialNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LocalConfigDisabled
 */
class ReadBasicInformationLocalConfigDisabled : public ReadAttribute {
public:
    ReadBasicInformationLocalConfigDisabled()
        : ReadAttribute("local-config-disabled")
    {
    }

    ~ReadBasicInformationLocalConfigDisabled() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeLocalConfigDisabledWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.LocalConfigDisabled response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation LocalConfigDisabled read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBasicInformationLocalConfigDisabled : public WriteAttribute {
public:
    WriteBasicInformationLocalConfigDisabled()
        : WriteAttribute("local-config-disabled")
    {
        AddArgument("attr-name", "local-config-disabled");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBasicInformationLocalConfigDisabled() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

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

private:
    bool mValue;
};

class SubscribeAttributeBasicInformationLocalConfigDisabled : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationLocalConfigDisabled()
        : SubscribeAttribute("local-config-disabled")
    {
    }

    ~SubscribeAttributeBasicInformationLocalConfigDisabled() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeLocalConfigDisabledWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.LocalConfigDisabled response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Reachable
 */
class ReadBasicInformationReachable : public ReadAttribute {
public:
    ReadBasicInformationReachable()
        : ReadAttribute("reachable")
    {
    }

    ~ReadBasicInformationReachable() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeReachableWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.Reachable response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation Reachable read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationReachable : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationReachable()
        : SubscribeAttribute("reachable")
    {
    }

    ~SubscribeAttributeBasicInformationReachable() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeReachableWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.Reachable response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UniqueID
 */
class ReadBasicInformationUniqueID : public ReadAttribute {
public:
    ReadBasicInformationUniqueID()
        : ReadAttribute("unique-id")
    {
    }

    ~ReadBasicInformationUniqueID() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeUniqueIDWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.UniqueID response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation UniqueID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationUniqueID : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationUniqueID()
        : SubscribeAttribute("unique-id")
    {
    }

    ~SubscribeAttributeBasicInformationUniqueID() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeUniqueIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.UniqueID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CapabilityMinima
 */
class ReadBasicInformationCapabilityMinima : public ReadAttribute {
public:
    ReadBasicInformationCapabilityMinima()
        : ReadAttribute("capability-minima")
    {
    }

    ~ReadBasicInformationCapabilityMinima() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeCapabilityMinimaWithCompletion:^(
            MTRBasicInformationClusterCapabilityMinimaStruct * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.CapabilityMinima response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation CapabilityMinima read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicInformationCapabilityMinima : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationCapabilityMinima()
        : SubscribeAttribute("capability-minima")
    {
    }

    ~SubscribeAttributeBasicInformationCapabilityMinima() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeCapabilityMinimaWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRBasicInformationClusterCapabilityMinimaStruct * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.CapabilityMinima response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductAppearance
 */
class ReadBasicInformationProductAppearance : public ReadAttribute {
public:
    ReadBasicInformationProductAppearance()
        : ReadAttribute("product-appearance")
    {
    }

    ~ReadBasicInformationProductAppearance() {}

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

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

class SubscribeAttributeBasicInformationProductAppearance : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationProductAppearance()
        : SubscribeAttribute("product-appearance")
    {
    }

    ~SubscribeAttributeBasicInformationProductAppearance() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicInformationGeneratedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBasicInformationGeneratedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicInformationAcceptedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBasicInformationAcceptedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadBasicInformationEventList : public ReadAttribute {
public:
    ReadBasicInformationEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadBasicInformationEventList() {}

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

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

class SubscribeAttributeBasicInformationEventList : public SubscribeAttribute {
public:
    SubscribeAttributeBasicInformationEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeBasicInformationEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicInformationAttributeList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBasicInformationAttributeList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicInformationFeatureMap() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBasicInformationFeatureMap() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicInformationClusterRevision() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BasicInformation.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BasicInformation ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBasicInformationClusterRevision() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBasicInformation alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BasicInformation.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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateProvider alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateProvider alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadOtaSoftwareUpdateProviderEventList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadOtaSoftwareUpdateProviderEventList() {}

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

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

class SubscribeAttributeOtaSoftwareUpdateProviderEventList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateProvider alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OTASoftwareUpdateProvider.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateProvider alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateProvider alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateProvider alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StateTransition                                                   | 0x0000 |
| * VersionApplied                                                    | 0x0001 |
| * DownloadError                                                     | 0x0002 |
\*----------------------------------------------------------------------------*/

/*
 * Command AnnounceOTAProvider
 */
class OtaSoftwareUpdateRequestorAnnounceOTAProvider : public ClusterCommand {
public:
    OtaSoftwareUpdateRequestorAnnounceOTAProvider()
        : ClusterCommand("announce-otaprovider")
    {
        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);
        __auto_type * 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-otaproviders")
    {
    }

    ~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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * 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-otaproviders")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "default-otaproviders");
        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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                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-otaproviders")
    {
    }

    ~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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadOtaSoftwareUpdateRequestorEventList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorEventList() {}

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

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

class SubscribeAttributeOtaSoftwareUpdateRequestorEventList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OTASoftwareUpdateRequestor.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOTASoftwareUpdateRequestor alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadLocalizationConfigurationEventList : public ReadAttribute {
public:
    ReadLocalizationConfigurationEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadLocalizationConfigurationEventList() {}

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

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

class SubscribeAttributeLocalizationConfigurationEventList : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadTimeFormatLocalizationEventList : public ReadAttribute {
public:
    ReadTimeFormatLocalizationEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadTimeFormatLocalizationEventList() {}

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

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

class SubscribeAttributeTimeFormatLocalizationEventList : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadUnitLocalizationEventList : public ReadAttribute {
public:
    ReadUnitLocalizationEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadUnitLocalizationEventList() {}

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

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

class SubscribeAttributeUnitLocalizationEventList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeUnitLocalizationEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadPowerSourceConfigurationEventList : public ReadAttribute {
public:
    ReadPowerSourceConfigurationEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadPowerSourceConfigurationEventList() {}

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

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

class SubscribeAttributePowerSourceConfigurationEventList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * WiredFaultChange                                                  | 0x0000 |
| * BatFaultChange                                                    | 0x0001 |
| * BatChargeFaultChange                                              | 0x0002 |
\*----------------------------------------------------------------------------*/

/*
 * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadPowerSourceEventList : public ReadAttribute {
public:
    ReadPowerSourceEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadPowerSourceEventList() {}

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

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

class SubscribeAttributePowerSourceEventList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributePowerSourceEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadGeneralCommissioningEventList : public ReadAttribute {
public:
    ReadGeneralCommissioningEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadGeneralCommissioningEventList() {}

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

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

class SubscribeAttributeGeneralCommissioningEventList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeGeneralCommissioningEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadNetworkCommissioningEventList : public ReadAttribute {
public:
    ReadNetworkCommissioningEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadNetworkCommissioningEventList() {}

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

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

class SubscribeAttributeNetworkCommissioningEventList : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeNetworkCommissioningEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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)];
        if (mRequest.transferFileDesignator.HasValue()) {
            params.transferFileDesignator = [[NSString alloc] initWithBytes:mRequest.transferFileDesignator.Value().data()
                                                                     length:mRequest.transferFileDesignator.Value().size()
                                                                   encoding:NSUTF8StringEncoding];
        } else {
            params.transferFileDesignator = nil;
        }
        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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadDiagnosticLogsEventList : public ReadAttribute {
public:
    ReadDiagnosticLogsEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadDiagnosticLogsEventList() {}

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

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

class SubscribeAttributeDiagnosticLogsEventList : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeDiagnosticLogsEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * BootReason                                                        | 0x0004 |
| * ActiveHardwareFaults                                              | 0x0005 |
| * ActiveRadioFaults                                                 | 0x0006 |
| * ActiveNetworkFaults                                               | 0x0007 |
| * TestEventTriggersEnabled                                          | 0x0008 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 BootReason
 */
class ReadGeneralDiagnosticsBootReason : public ReadAttribute {
public:
    ReadGeneralDiagnosticsBootReason()
        : ReadAttribute("boot-reason")
    {
    }

    ~ReadGeneralDiagnosticsBootReason() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        [cluster readAttributeBootReasonWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.BootReason response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics BootReason read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsBootReason : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsBootReason()
        : SubscribeAttribute("boot-reason")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsBootReason() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeBootReasonWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.BootReason 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadGeneralDiagnosticsEventList : public ReadAttribute {
public:
    ReadGeneralDiagnosticsEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadGeneralDiagnosticsEventList() {}

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

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

class SubscribeAttributeGeneralDiagnosticsEventList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadSoftwareDiagnosticsEventList : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadSoftwareDiagnosticsEventList() {}

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

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

class SubscribeAttributeSoftwareDiagnosticsEventList : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * NeighborTable                                                     | 0x0007 |
| * RouteTable                                                        | 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 NeighborTable
 */
class ReadThreadNetworkDiagnosticsNeighborTable : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsNeighborTable()
        : ReadAttribute("neighbor-table")
    {
    }

    ~ReadThreadNetworkDiagnosticsNeighborTable() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        [cluster readAttributeNeighborTableWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.NeighborTable response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics NeighborTable read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsNeighborTable : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsNeighborTable()
        : SubscribeAttribute("neighbor-table")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsNeighborTable() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNeighborTableWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.NeighborTable response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RouteTable
 */
class ReadThreadNetworkDiagnosticsRouteTable : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRouteTable()
        : ReadAttribute("route-table")
    {
    }

    ~ReadThreadNetworkDiagnosticsRouteTable() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        [cluster readAttributeRouteTableWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RouteTable response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RouteTable read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRouteTable : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRouteTable()
        : SubscribeAttribute("route-table")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRouteTable() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeRouteTableWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RouteTable 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadThreadNetworkDiagnosticsEventList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsEventList() {}

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

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

class SubscribeAttributeThreadNetworkDiagnosticsEventList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadWiFiNetworkDiagnosticsEventList : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadWiFiNetworkDiagnosticsEventList() {}

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

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

class SubscribeAttributeWiFiNetworkDiagnosticsEventList : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadEthernetNetworkDiagnosticsEventList : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadEthernetNetworkDiagnosticsEventList() {}

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

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

class SubscribeAttributeEthernetNetworkDiagnosticsEventList : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 BridgedDeviceBasicInformation                               | 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 |
| * ProductAppearance                                                 | 0x0014 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StartUp                                                           | 0x0000 |
| * ShutDown                                                          | 0x0001 |
| * Leave                                                             | 0x0002 |
| * ReachableChanged                                                  | 0x0003 |
\*----------------------------------------------------------------------------*/

/*
 * Attribute VendorName
 */
class ReadBridgedDeviceBasicInformationVendorName : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationVendorName()
        : ReadAttribute("vendor-name")
    {
    }

    ~ReadBridgedDeviceBasicInformationVendorName() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeVendorNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.VendorName response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation VendorName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationVendorName : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationVendorName()
        : SubscribeAttribute("vendor-name")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationVendorName() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeVendorNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.VendorName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorID
 */
class ReadBridgedDeviceBasicInformationVendorID : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationVendorID()
        : ReadAttribute("vendor-id")
    {
    }

    ~ReadBridgedDeviceBasicInformationVendorID() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeVendorIDWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.VendorID response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation VendorID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationVendorID : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationVendorID()
        : SubscribeAttribute("vendor-id")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationVendorID() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeVendorIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.VendorID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductName
 */
class ReadBridgedDeviceBasicInformationProductName : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationProductName()
        : ReadAttribute("product-name")
    {
    }

    ~ReadBridgedDeviceBasicInformationProductName() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeProductNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.ProductName response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation ProductName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationProductName : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationProductName()
        : SubscribeAttribute("product-name")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationProductName() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeProductNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.ProductName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NodeLabel
 */
class ReadBridgedDeviceBasicInformationNodeLabel : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationNodeLabel()
        : ReadAttribute("node-label")
    {
    }

    ~ReadBridgedDeviceBasicInformationNodeLabel() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeNodeLabelWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.NodeLabel response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation NodeLabel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBridgedDeviceBasicInformationNodeLabel : public WriteAttribute {
public:
    WriteBridgedDeviceBasicInformationNodeLabel()
        : WriteAttribute("node-label")
    {
        AddArgument("attr-name", "node-label");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBridgedDeviceBasicInformationNodeLabel() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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("BridgedDeviceBasicInformation NodeLabel write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBridgedDeviceBasicInformationNodeLabel : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationNodeLabel()
        : SubscribeAttribute("node-label")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationNodeLabel() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNodeLabelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.NodeLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareVersion
 */
class ReadBridgedDeviceBasicInformationHardwareVersion : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationHardwareVersion()
        : ReadAttribute("hardware-version")
    {
    }

    ~ReadBridgedDeviceBasicInformationHardwareVersion() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeHardwareVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.HardwareVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation HardwareVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationHardwareVersion : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationHardwareVersion()
        : SubscribeAttribute("hardware-version")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationHardwareVersion() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeHardwareVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.HardwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareVersionString
 */
class ReadBridgedDeviceBasicInformationHardwareVersionString : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationHardwareVersionString()
        : ReadAttribute("hardware-version-string")
    {
    }

    ~ReadBridgedDeviceBasicInformationHardwareVersionString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeHardwareVersionStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.HardwareVersionString response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation HardwareVersionString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationHardwareVersionString : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationHardwareVersionString()
        : SubscribeAttribute("hardware-version-string")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationHardwareVersionString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeHardwareVersionStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.HardwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoftwareVersion
 */
class ReadBridgedDeviceBasicInformationSoftwareVersion : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationSoftwareVersion()
        : ReadAttribute("software-version")
    {
    }

    ~ReadBridgedDeviceBasicInformationSoftwareVersion() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeSoftwareVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.SoftwareVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation SoftwareVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationSoftwareVersion : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationSoftwareVersion()
        : SubscribeAttribute("software-version")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationSoftwareVersion() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeSoftwareVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.SoftwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoftwareVersionString
 */
class ReadBridgedDeviceBasicInformationSoftwareVersionString : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationSoftwareVersionString()
        : ReadAttribute("software-version-string")
    {
    }

    ~ReadBridgedDeviceBasicInformationSoftwareVersionString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeSoftwareVersionStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.SoftwareVersionString response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation SoftwareVersionString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationSoftwareVersionString : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationSoftwareVersionString()
        : SubscribeAttribute("software-version-string")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationSoftwareVersionString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeSoftwareVersionStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.SoftwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ManufacturingDate
 */
class ReadBridgedDeviceBasicInformationManufacturingDate : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationManufacturingDate()
        : ReadAttribute("manufacturing-date")
    {
    }

    ~ReadBridgedDeviceBasicInformationManufacturingDate() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeManufacturingDateWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.ManufacturingDate response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation ManufacturingDate read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationManufacturingDate : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationManufacturingDate()
        : SubscribeAttribute("manufacturing-date")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationManufacturingDate() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeManufacturingDateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.ManufacturingDate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PartNumber
 */
class ReadBridgedDeviceBasicInformationPartNumber : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationPartNumber()
        : ReadAttribute("part-number")
    {
    }

    ~ReadBridgedDeviceBasicInformationPartNumber() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributePartNumberWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.PartNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation PartNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationPartNumber : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationPartNumber()
        : SubscribeAttribute("part-number")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationPartNumber() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributePartNumberWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.PartNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductURL
 */
class ReadBridgedDeviceBasicInformationProductURL : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationProductURL()
        : ReadAttribute("product-url")
    {
    }

    ~ReadBridgedDeviceBasicInformationProductURL() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeProductURLWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.ProductURL response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation ProductURL read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationProductURL : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationProductURL()
        : SubscribeAttribute("product-url")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationProductURL() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeProductURLWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.ProductURL response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductLabel
 */
class ReadBridgedDeviceBasicInformationProductLabel : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationProductLabel()
        : ReadAttribute("product-label")
    {
    }

    ~ReadBridgedDeviceBasicInformationProductLabel() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeProductLabelWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.ProductLabel response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation ProductLabel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationProductLabel : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationProductLabel()
        : SubscribeAttribute("product-label")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationProductLabel() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeProductLabelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.ProductLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SerialNumber
 */
class ReadBridgedDeviceBasicInformationSerialNumber : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationSerialNumber()
        : ReadAttribute("serial-number")
    {
    }

    ~ReadBridgedDeviceBasicInformationSerialNumber() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeSerialNumberWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.SerialNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation SerialNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationSerialNumber : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationSerialNumber()
        : SubscribeAttribute("serial-number")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationSerialNumber() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeSerialNumberWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.SerialNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Reachable
 */
class ReadBridgedDeviceBasicInformationReachable : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationReachable()
        : ReadAttribute("reachable")
    {
    }

    ~ReadBridgedDeviceBasicInformationReachable() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeReachableWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.Reachable response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation Reachable read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationReachable : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationReachable()
        : SubscribeAttribute("reachable")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationReachable() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeReachableWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.Reachable response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UniqueID
 */
class ReadBridgedDeviceBasicInformationUniqueID : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationUniqueID()
        : ReadAttribute("unique-id")
    {
    }

    ~ReadBridgedDeviceBasicInformationUniqueID() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeUniqueIDWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.UniqueID response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation UniqueID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicInformationUniqueID : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationUniqueID()
        : SubscribeAttribute("unique-id")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationUniqueID() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeUniqueIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.UniqueID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductAppearance
 */
class ReadBridgedDeviceBasicInformationProductAppearance : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationProductAppearance()
        : ReadAttribute("product-appearance")
    {
    }

    ~ReadBridgedDeviceBasicInformationProductAppearance() {}

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

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

class SubscribeAttributeBridgedDeviceBasicInformationProductAppearance : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationProductAppearance()
        : SubscribeAttribute("product-appearance")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationProductAppearance() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBridgedDeviceBasicInformationGeneratedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBridgedDeviceBasicInformationGeneratedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBridgedDeviceBasicInformationAcceptedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBridgedDeviceBasicInformationAcceptedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadBridgedDeviceBasicInformationEventList : public ReadAttribute {
public:
    ReadBridgedDeviceBasicInformationEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadBridgedDeviceBasicInformationEventList() {}

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

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

class SubscribeAttributeBridgedDeviceBasicInformationEventList : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicInformationEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicInformationEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBridgedDeviceBasicInformationAttributeList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBridgedDeviceBasicInformationAttributeList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBridgedDeviceBasicInformationFeatureMap() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBridgedDeviceBasicInformationFeatureMap() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBridgedDeviceBasicInformationClusterRevision() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasicInformation.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasicInformation ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

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

    ~SubscribeAttributeBridgedDeviceBasicInformationClusterRevision() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBridgedDeviceBasicInformation alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasicInformation.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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadSwitchEventList : public ReadAttribute {
public:
    ReadSwitchEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadSwitchEventList() {}

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

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

class SubscribeAttributeSwitchEventList : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeSwitchEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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("PAKEPasscodeVerifier", &mRequest.PAKEPasscodeVerifier);
        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);
        __auto_type * 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.pakePasscodeVerifier = [NSData dataWithBytes:mRequest.PAKEPasscodeVerifier.data()
                                                     length:mRequest.PAKEPasscodeVerifier.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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadAdministratorCommissioningEventList : public ReadAttribute {
public:
    ReadAdministratorCommissioningEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadAdministratorCommissioningEventList() {}

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

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

class SubscribeAttributeAdministratorCommissioningEventList : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device
                                                                                      endpointID:@(endpointId)
                                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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:chip::to_underlying(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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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("RootCACertificate", &mRequest.rootCACertificate);
        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);
        __auto_type * 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.rootCACertificate = [NSData dataWithBytes:mRequest.rootCACertificate.data()
                                                  length:mRequest.rootCACertificate.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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadOperationalCredentialsEventList : public ReadAttribute {
public:
    ReadOperationalCredentialsEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadOperationalCredentialsEventList() {}

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

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

class SubscribeAttributeOperationalCredentialsEventList : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeOperationalCredentialsEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadGroupKeyManagementEventList : public ReadAttribute {
public:
    ReadGroupKeyManagementEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadGroupKeyManagementEventList() {}

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

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

class SubscribeAttributeGroupKeyManagementEventList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeGroupKeyManagementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadFixedLabelEventList : public ReadAttribute {
public:
    ReadFixedLabelEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadFixedLabelEventList() {}

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

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

class SubscribeAttributeFixedLabelEventList : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeFixedLabelEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                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);
        __auto_type * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadUserLabelEventList : public ReadAttribute {
public:
    ReadUserLabelEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadUserLabelEventList() {}

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

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

class SubscribeAttributeUserLabelEventList : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeUserLabelEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadBooleanStateEventList : public ReadAttribute {
public:
    ReadBooleanStateEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadBooleanStateEventList() {}

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

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

class SubscribeAttributeBooleanStateEventList : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeBooleanStateEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadModeSelectEventList : public ReadAttribute {
public:
    ReadModeSelectEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadModeSelectEventList() {}

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

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

class SubscribeAttributeModeSelectEventList : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeModeSelectEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 TemperatureControl                                          | 0x0056 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * SetTemperature                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * TemperatureSetpoint                                               | 0x0000 |
| * MinTemperature                                                    | 0x0001 |
| * MaxTemperature                                                    | 0x0002 |
| * Step                                                              | 0x0003 |
| * CurrentTemperatureLevelIndex                                      | 0x0004 |
| * SupportedTemperatureLevels                                        | 0x0005 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command SetTemperature
 */
class TemperatureControlSetTemperature : public ClusterCommand {
public:
    TemperatureControlSetTemperature()
        : ClusterCommand("set-temperature")
    {
        AddArgument("TargetTemperature", INT16_MIN, INT16_MAX, &mRequest.targetTemperature);
        AddArgument("TargetTemperatureLevel", 0, UINT8_MAX, &mRequest.targetTemperatureLevel);
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterTemperatureControl alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRTemperatureControlClusterSetTemperatureParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.targetTemperature.HasValue()) {
            params.targetTemperature = [NSNumber numberWithShort:mRequest.targetTemperature.Value()];
        } else {
            params.targetTemperature = nil;
        }
        if (mRequest.targetTemperatureLevel.HasValue()) {
            params.targetTemperatureLevel = [NSNumber numberWithUnsignedChar:mRequest.targetTemperatureLevel.Value()];
        } else {
            params.targetTemperatureLevel = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster setTemperatureWithParams: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::TemperatureControl::Commands::SetTemperature::Type mRequest;
};

/*
 * Attribute TemperatureSetpoint
 */
class ReadTemperatureControlTemperatureSetpoint : public ReadAttribute {
public:
    ReadTemperatureControlTemperatureSetpoint()
        : ReadAttribute("temperature-setpoint")
    {
    }

    ~ReadTemperatureControlTemperatureSetpoint() {}

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

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

class SubscribeAttributeTemperatureControlTemperatureSetpoint : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureControlTemperatureSetpoint()
        : SubscribeAttribute("temperature-setpoint")
    {
    }

    ~SubscribeAttributeTemperatureControlTemperatureSetpoint() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinTemperature
 */
class ReadTemperatureControlMinTemperature : public ReadAttribute {
public:
    ReadTemperatureControlMinTemperature()
        : ReadAttribute("min-temperature")
    {
    }

    ~ReadTemperatureControlMinTemperature() {}

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

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

class SubscribeAttributeTemperatureControlMinTemperature : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureControlMinTemperature()
        : SubscribeAttribute("min-temperature")
    {
    }

    ~SubscribeAttributeTemperatureControlMinTemperature() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxTemperature
 */
class ReadTemperatureControlMaxTemperature : public ReadAttribute {
public:
    ReadTemperatureControlMaxTemperature()
        : ReadAttribute("max-temperature")
    {
    }

    ~ReadTemperatureControlMaxTemperature() {}

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

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

class SubscribeAttributeTemperatureControlMaxTemperature : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureControlMaxTemperature()
        : SubscribeAttribute("max-temperature")
    {
    }

    ~SubscribeAttributeTemperatureControlMaxTemperature() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Step
 */
class ReadTemperatureControlStep : public ReadAttribute {
public:
    ReadTemperatureControlStep()
        : ReadAttribute("step")
    {
    }

    ~ReadTemperatureControlStep() {}

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

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

class SubscribeAttributeTemperatureControlStep : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureControlStep()
        : SubscribeAttribute("step")
    {
    }

    ~SubscribeAttributeTemperatureControlStep() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentTemperatureLevelIndex
 */
class ReadTemperatureControlCurrentTemperatureLevelIndex : public ReadAttribute {
public:
    ReadTemperatureControlCurrentTemperatureLevelIndex()
        : ReadAttribute("current-temperature-level-index")
    {
    }

    ~ReadTemperatureControlCurrentTemperatureLevelIndex() {}

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

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

class SubscribeAttributeTemperatureControlCurrentTemperatureLevelIndex : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureControlCurrentTemperatureLevelIndex()
        : SubscribeAttribute("current-temperature-level-index")
    {
    }

    ~SubscribeAttributeTemperatureControlCurrentTemperatureLevelIndex() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedTemperatureLevels
 */
class ReadTemperatureControlSupportedTemperatureLevels : public ReadAttribute {
public:
    ReadTemperatureControlSupportedTemperatureLevels()
        : ReadAttribute("supported-temperature-levels")
    {
    }

    ~ReadTemperatureControlSupportedTemperatureLevels() {}

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

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

class SubscribeAttributeTemperatureControlSupportedTemperatureLevels : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureControlSupportedTemperatureLevels()
        : SubscribeAttribute("supported-temperature-levels")
    {
    }

    ~SubscribeAttributeTemperatureControlSupportedTemperatureLevels() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadTemperatureControlGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeTemperatureControlGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadTemperatureControlAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeTemperatureControlAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadTemperatureControlEventList : public ReadAttribute {
public:
    ReadTemperatureControlEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadTemperatureControlEventList() {}

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

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

class SubscribeAttributeTemperatureControlEventList : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureControlEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeTemperatureControlEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadTemperatureControlAttributeList() {}

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

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

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

    ~SubscribeAttributeTemperatureControlAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadTemperatureControlFeatureMap() {}

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

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

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

    ~SubscribeAttributeTemperatureControlFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadTemperatureControlClusterRevision() {}

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

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

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

    ~SubscribeAttributeTemperatureControlClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster RefrigeratorAlarm                                           | 0x0057 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * Reset                                                             |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Mask                                                              | 0x0000 |
| * Latch                                                             | 0x0001 |
| * State                                                             | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * Notify                                                            | 0x0000 |
\*----------------------------------------------------------------------------*/

/*
 * Command Reset
 */
class RefrigeratorAlarmReset : public ClusterCommand {
public:
    RefrigeratorAlarmReset()
        : ClusterCommand("reset")
    {
        AddArgument("Alarms", 0, UINT32_MAX, &mRequest.alarms);
        AddArgument("Mask", 0, UINT32_MAX, &mRequest.mask);
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterRefrigeratorAlarm alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRRefrigeratorAlarmClusterResetParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.alarms = [NSNumber numberWithUnsignedInt:mRequest.alarms.Raw()];
        if (mRequest.mask.HasValue()) {
            params.mask = [NSNumber numberWithUnsignedInt:mRequest.mask.Value().Raw()];
        } else {
            params.mask = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster resetWithParams: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::RefrigeratorAlarm::Commands::Reset::Type mRequest;
};

/*
 * Attribute Mask
 */
class ReadRefrigeratorAlarmMask : public ReadAttribute {
public:
    ReadRefrigeratorAlarmMask()
        : ReadAttribute("mask")
    {
    }

    ~ReadRefrigeratorAlarmMask() {}

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

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

class WriteRefrigeratorAlarmMask : public WriteAttribute {
public:
    WriteRefrigeratorAlarmMask()
        : WriteAttribute("mask")
    {
        AddArgument("attr-name", "mask");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteRefrigeratorAlarmMask() {}

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

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

private:
    uint32_t mValue;
};

class SubscribeAttributeRefrigeratorAlarmMask : public SubscribeAttribute {
public:
    SubscribeAttributeRefrigeratorAlarmMask()
        : SubscribeAttribute("mask")
    {
    }

    ~SubscribeAttributeRefrigeratorAlarmMask() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Latch
 */
class ReadRefrigeratorAlarmLatch : public ReadAttribute {
public:
    ReadRefrigeratorAlarmLatch()
        : ReadAttribute("latch")
    {
    }

    ~ReadRefrigeratorAlarmLatch() {}

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

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

class SubscribeAttributeRefrigeratorAlarmLatch : public SubscribeAttribute {
public:
    SubscribeAttributeRefrigeratorAlarmLatch()
        : SubscribeAttribute("latch")
    {
    }

    ~SubscribeAttributeRefrigeratorAlarmLatch() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute State
 */
class ReadRefrigeratorAlarmState : public ReadAttribute {
public:
    ReadRefrigeratorAlarmState()
        : ReadAttribute("state")
    {
    }

    ~ReadRefrigeratorAlarmState() {}

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

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

class SubscribeAttributeRefrigeratorAlarmState : public SubscribeAttribute {
public:
    SubscribeAttributeRefrigeratorAlarmState()
        : SubscribeAttribute("state")
    {
    }

    ~SubscribeAttributeRefrigeratorAlarmState() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadRefrigeratorAlarmGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeRefrigeratorAlarmGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadRefrigeratorAlarmAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeRefrigeratorAlarmAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadRefrigeratorAlarmEventList : public ReadAttribute {
public:
    ReadRefrigeratorAlarmEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadRefrigeratorAlarmEventList() {}

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

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

class SubscribeAttributeRefrigeratorAlarmEventList : public SubscribeAttribute {
public:
    SubscribeAttributeRefrigeratorAlarmEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeRefrigeratorAlarmEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadRefrigeratorAlarmAttributeList() {}

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

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

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

    ~SubscribeAttributeRefrigeratorAlarmAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadRefrigeratorAlarmFeatureMap() {}

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

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

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

    ~SubscribeAttributeRefrigeratorAlarmFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadRefrigeratorAlarmClusterRevision() {}

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

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

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

    ~SubscribeAttributeRefrigeratorAlarmClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster AirQuality                                                  | 0x005B |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * AirQuality                                                        | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute AirQuality
 */
class ReadAirQualityAirQuality : public ReadAttribute {
public:
    ReadAirQualityAirQuality()
        : ReadAttribute("air-quality")
    {
    }

    ~ReadAirQualityAirQuality() {}

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

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

class SubscribeAttributeAirQualityAirQuality : public SubscribeAttribute {
public:
    SubscribeAttributeAirQualityAirQuality()
        : SubscribeAttribute("air-quality")
    {
    }

    ~SubscribeAttributeAirQualityAirQuality() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAirQualityGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeAirQualityGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAirQualityAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeAirQualityAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadAirQualityEventList : public ReadAttribute {
public:
    ReadAirQualityEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadAirQualityEventList() {}

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

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

class SubscribeAttributeAirQualityEventList : public SubscribeAttribute {
public:
    SubscribeAttributeAirQualityEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeAirQualityEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAirQualityAttributeList() {}

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

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

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

    ~SubscribeAttributeAirQualityAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAirQualityFeatureMap() {}

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

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

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

    ~SubscribeAttributeAirQualityFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAirQualityClusterRevision() {}

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

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

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

    ~SubscribeAttributeAirQualityClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster SmokeCoAlarm                                                | 0x005C |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * SelfTestRequest                                                   |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * ExpressedState                                                    | 0x0000 |
| * SmokeState                                                        | 0x0001 |
| * COState                                                           | 0x0002 |
| * BatteryAlert                                                      | 0x0003 |
| * DeviceMuted                                                       | 0x0004 |
| * TestInProgress                                                    | 0x0005 |
| * HardwareFaultAlert                                                | 0x0006 |
| * EndOfServiceAlert                                                 | 0x0007 |
| * InterconnectSmokeAlarm                                            | 0x0008 |
| * InterconnectCOAlarm                                               | 0x0009 |
| * ContaminationState                                                | 0x000A |
| * SensitivityLevel                                                  | 0x000B |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * SmokeAlarm                                                        | 0x0000 |
| * COAlarm                                                           | 0x0001 |
| * LowBattery                                                        | 0x0002 |
| * HardwareFault                                                     | 0x0003 |
| * EndOfService                                                      | 0x0004 |
| * SelfTestComplete                                                  | 0x0005 |
| * AlarmMuted                                                        | 0x0006 |
| * MuteEnded                                                         | 0x0007 |
| * InterconnectSmokeAlarm                                            | 0x0008 |
| * InterconnectCOAlarm                                               | 0x0009 |
| * AllClear                                                          | 0x000A |
\*----------------------------------------------------------------------------*/

/*
 * Command SelfTestRequest
 */
class SmokeCoAlarmSelfTestRequest : public ClusterCommand {
public:
    SmokeCoAlarmSelfTestRequest()
        : ClusterCommand("self-test-request")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterSmokeCOAlarm alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSmokeCOAlarmClusterSelfTestRequestParams 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 selfTestRequestWithParams: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 ExpressedState
 */
class ReadSmokeCoAlarmExpressedState : public ReadAttribute {
public:
    ReadSmokeCoAlarmExpressedState()
        : ReadAttribute("expressed-state")
    {
    }

    ~ReadSmokeCoAlarmExpressedState() {}

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

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

class SubscribeAttributeSmokeCoAlarmExpressedState : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmExpressedState()
        : SubscribeAttribute("expressed-state")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmExpressedState() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SmokeState
 */
class ReadSmokeCoAlarmSmokeState : public ReadAttribute {
public:
    ReadSmokeCoAlarmSmokeState()
        : ReadAttribute("smoke-state")
    {
    }

    ~ReadSmokeCoAlarmSmokeState() {}

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

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

class SubscribeAttributeSmokeCoAlarmSmokeState : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmSmokeState()
        : SubscribeAttribute("smoke-state")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmSmokeState() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute COState
 */
class ReadSmokeCoAlarmCOState : public ReadAttribute {
public:
    ReadSmokeCoAlarmCOState()
        : ReadAttribute("costate")
    {
    }

    ~ReadSmokeCoAlarmCOState() {}

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

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

class SubscribeAttributeSmokeCoAlarmCOState : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmCOState()
        : SubscribeAttribute("costate")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmCOState() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatteryAlert
 */
class ReadSmokeCoAlarmBatteryAlert : public ReadAttribute {
public:
    ReadSmokeCoAlarmBatteryAlert()
        : ReadAttribute("battery-alert")
    {
    }

    ~ReadSmokeCoAlarmBatteryAlert() {}

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

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

class SubscribeAttributeSmokeCoAlarmBatteryAlert : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmBatteryAlert()
        : SubscribeAttribute("battery-alert")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmBatteryAlert() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DeviceMuted
 */
class ReadSmokeCoAlarmDeviceMuted : public ReadAttribute {
public:
    ReadSmokeCoAlarmDeviceMuted()
        : ReadAttribute("device-muted")
    {
    }

    ~ReadSmokeCoAlarmDeviceMuted() {}

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

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

class SubscribeAttributeSmokeCoAlarmDeviceMuted : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmDeviceMuted()
        : SubscribeAttribute("device-muted")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmDeviceMuted() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TestInProgress
 */
class ReadSmokeCoAlarmTestInProgress : public ReadAttribute {
public:
    ReadSmokeCoAlarmTestInProgress()
        : ReadAttribute("test-in-progress")
    {
    }

    ~ReadSmokeCoAlarmTestInProgress() {}

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

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

class SubscribeAttributeSmokeCoAlarmTestInProgress : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmTestInProgress()
        : SubscribeAttribute("test-in-progress")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmTestInProgress() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareFaultAlert
 */
class ReadSmokeCoAlarmHardwareFaultAlert : public ReadAttribute {
public:
    ReadSmokeCoAlarmHardwareFaultAlert()
        : ReadAttribute("hardware-fault-alert")
    {
    }

    ~ReadSmokeCoAlarmHardwareFaultAlert() {}

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

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

class SubscribeAttributeSmokeCoAlarmHardwareFaultAlert : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmHardwareFaultAlert()
        : SubscribeAttribute("hardware-fault-alert")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmHardwareFaultAlert() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EndOfServiceAlert
 */
class ReadSmokeCoAlarmEndOfServiceAlert : public ReadAttribute {
public:
    ReadSmokeCoAlarmEndOfServiceAlert()
        : ReadAttribute("end-of-service-alert")
    {
    }

    ~ReadSmokeCoAlarmEndOfServiceAlert() {}

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

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

class SubscribeAttributeSmokeCoAlarmEndOfServiceAlert : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmEndOfServiceAlert()
        : SubscribeAttribute("end-of-service-alert")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmEndOfServiceAlert() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InterconnectSmokeAlarm
 */
class ReadSmokeCoAlarmInterconnectSmokeAlarm : public ReadAttribute {
public:
    ReadSmokeCoAlarmInterconnectSmokeAlarm()
        : ReadAttribute("interconnect-smoke-alarm")
    {
    }

    ~ReadSmokeCoAlarmInterconnectSmokeAlarm() {}

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

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

class SubscribeAttributeSmokeCoAlarmInterconnectSmokeAlarm : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmInterconnectSmokeAlarm()
        : SubscribeAttribute("interconnect-smoke-alarm")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmInterconnectSmokeAlarm() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InterconnectCOAlarm
 */
class ReadSmokeCoAlarmInterconnectCOAlarm : public ReadAttribute {
public:
    ReadSmokeCoAlarmInterconnectCOAlarm()
        : ReadAttribute("interconnect-coalarm")
    {
    }

    ~ReadSmokeCoAlarmInterconnectCOAlarm() {}

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

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

class SubscribeAttributeSmokeCoAlarmInterconnectCOAlarm : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmInterconnectCOAlarm()
        : SubscribeAttribute("interconnect-coalarm")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmInterconnectCOAlarm() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ContaminationState
 */
class ReadSmokeCoAlarmContaminationState : public ReadAttribute {
public:
    ReadSmokeCoAlarmContaminationState()
        : ReadAttribute("contamination-state")
    {
    }

    ~ReadSmokeCoAlarmContaminationState() {}

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

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

class SubscribeAttributeSmokeCoAlarmContaminationState : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmContaminationState()
        : SubscribeAttribute("contamination-state")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmContaminationState() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SensitivityLevel
 */
class ReadSmokeCoAlarmSensitivityLevel : public ReadAttribute {
public:
    ReadSmokeCoAlarmSensitivityLevel()
        : ReadAttribute("sensitivity-level")
    {
    }

    ~ReadSmokeCoAlarmSensitivityLevel() {}

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

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

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

    ~WriteSmokeCoAlarmSensitivityLevel() {}

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

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

private:
    uint8_t mValue;
};

class SubscribeAttributeSmokeCoAlarmSensitivityLevel : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmSensitivityLevel()
        : SubscribeAttribute("sensitivity-level")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmSensitivityLevel() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadSmokeCoAlarmGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeSmokeCoAlarmGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadSmokeCoAlarmAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeSmokeCoAlarmAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadSmokeCoAlarmEventList : public ReadAttribute {
public:
    ReadSmokeCoAlarmEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadSmokeCoAlarmEventList() {}

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

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

class SubscribeAttributeSmokeCoAlarmEventList : public SubscribeAttribute {
public:
    SubscribeAttributeSmokeCoAlarmEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeSmokeCoAlarmEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadSmokeCoAlarmAttributeList() {}

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

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

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

    ~SubscribeAttributeSmokeCoAlarmAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadSmokeCoAlarmFeatureMap() {}

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

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

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

    ~SubscribeAttributeSmokeCoAlarmFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadSmokeCoAlarmClusterRevision() {}

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

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

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

    ~SubscribeAttributeSmokeCoAlarmClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster HepaFilterMonitoring                                        | 0x0071 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class HepaFilterMonitoringResetCondition : public ClusterCommand {
public:
    HepaFilterMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterHEPAFilterMonitoring alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRHEPAFilterMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadHepaFilterMonitoringCondition : public ReadAttribute {
public:
    ReadHepaFilterMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadHepaFilterMonitoringCondition() {}

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

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

class SubscribeAttributeHepaFilterMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeHepaFilterMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeHepaFilterMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadHepaFilterMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadHepaFilterMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadHepaFilterMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeHepaFilterMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeHepaFilterMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeHepaFilterMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadHepaFilterMonitoringChangeIndication : public ReadAttribute {
public:
    ReadHepaFilterMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadHepaFilterMonitoringChangeIndication() {}

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

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

class SubscribeAttributeHepaFilterMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeHepaFilterMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeHepaFilterMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadHepaFilterMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadHepaFilterMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadHepaFilterMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeHepaFilterMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeHepaFilterMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeHepaFilterMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadHepaFilterMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeHepaFilterMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadHepaFilterMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeHepaFilterMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadHepaFilterMonitoringEventList : public ReadAttribute {
public:
    ReadHepaFilterMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadHepaFilterMonitoringEventList() {}

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

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

class SubscribeAttributeHepaFilterMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeHepaFilterMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeHepaFilterMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadHepaFilterMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeHepaFilterMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadHepaFilterMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeHepaFilterMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadHepaFilterMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeHepaFilterMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ActivatedCarbonFilterMonitoring                             | 0x0072 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class ActivatedCarbonFilterMonitoringResetCondition : public ClusterCommand {
public:
    ActivatedCarbonFilterMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterActivatedCarbonFilterMonitoring alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRActivatedCarbonFilterMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadActivatedCarbonFilterMonitoringCondition : public ReadAttribute {
public:
    ReadActivatedCarbonFilterMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadActivatedCarbonFilterMonitoringCondition() {}

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

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

class SubscribeAttributeActivatedCarbonFilterMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeActivatedCarbonFilterMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeActivatedCarbonFilterMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadActivatedCarbonFilterMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadActivatedCarbonFilterMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadActivatedCarbonFilterMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeActivatedCarbonFilterMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeActivatedCarbonFilterMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeActivatedCarbonFilterMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadActivatedCarbonFilterMonitoringChangeIndication : public ReadAttribute {
public:
    ReadActivatedCarbonFilterMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadActivatedCarbonFilterMonitoringChangeIndication() {}

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

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

class SubscribeAttributeActivatedCarbonFilterMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeActivatedCarbonFilterMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeActivatedCarbonFilterMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadActivatedCarbonFilterMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadActivatedCarbonFilterMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadActivatedCarbonFilterMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeActivatedCarbonFilterMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeActivatedCarbonFilterMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeActivatedCarbonFilterMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadActivatedCarbonFilterMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeActivatedCarbonFilterMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadActivatedCarbonFilterMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeActivatedCarbonFilterMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadActivatedCarbonFilterMonitoringEventList : public ReadAttribute {
public:
    ReadActivatedCarbonFilterMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadActivatedCarbonFilterMonitoringEventList() {}

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

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

class SubscribeAttributeActivatedCarbonFilterMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeActivatedCarbonFilterMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeActivatedCarbonFilterMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadActivatedCarbonFilterMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeActivatedCarbonFilterMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadActivatedCarbonFilterMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeActivatedCarbonFilterMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadActivatedCarbonFilterMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeActivatedCarbonFilterMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster CeramicFilterMonitoring                                     | 0x0073 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class CeramicFilterMonitoringResetCondition : public ClusterCommand {
public:
    CeramicFilterMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterCeramicFilterMonitoring alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRCeramicFilterMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadCeramicFilterMonitoringCondition : public ReadAttribute {
public:
    ReadCeramicFilterMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadCeramicFilterMonitoringCondition() {}

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

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

class SubscribeAttributeCeramicFilterMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeCeramicFilterMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeCeramicFilterMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadCeramicFilterMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadCeramicFilterMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadCeramicFilterMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeCeramicFilterMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeCeramicFilterMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeCeramicFilterMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadCeramicFilterMonitoringChangeIndication : public ReadAttribute {
public:
    ReadCeramicFilterMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadCeramicFilterMonitoringChangeIndication() {}

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

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

class SubscribeAttributeCeramicFilterMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeCeramicFilterMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeCeramicFilterMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadCeramicFilterMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadCeramicFilterMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadCeramicFilterMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeCeramicFilterMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeCeramicFilterMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeCeramicFilterMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadCeramicFilterMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeCeramicFilterMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadCeramicFilterMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeCeramicFilterMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadCeramicFilterMonitoringEventList : public ReadAttribute {
public:
    ReadCeramicFilterMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadCeramicFilterMonitoringEventList() {}

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

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

class SubscribeAttributeCeramicFilterMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeCeramicFilterMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeCeramicFilterMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadCeramicFilterMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeCeramicFilterMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadCeramicFilterMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeCeramicFilterMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadCeramicFilterMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeCeramicFilterMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ElectrostaticFilterMonitoring                               | 0x0074 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class ElectrostaticFilterMonitoringResetCondition : public ClusterCommand {
public:
    ElectrostaticFilterMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterElectrostaticFilterMonitoring alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRElectrostaticFilterMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadElectrostaticFilterMonitoringCondition : public ReadAttribute {
public:
    ReadElectrostaticFilterMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadElectrostaticFilterMonitoringCondition() {}

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

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

class SubscribeAttributeElectrostaticFilterMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeElectrostaticFilterMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeElectrostaticFilterMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadElectrostaticFilterMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadElectrostaticFilterMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadElectrostaticFilterMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeElectrostaticFilterMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeElectrostaticFilterMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeElectrostaticFilterMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadElectrostaticFilterMonitoringChangeIndication : public ReadAttribute {
public:
    ReadElectrostaticFilterMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadElectrostaticFilterMonitoringChangeIndication() {}

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

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

class SubscribeAttributeElectrostaticFilterMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeElectrostaticFilterMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeElectrostaticFilterMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadElectrostaticFilterMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadElectrostaticFilterMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadElectrostaticFilterMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeElectrostaticFilterMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeElectrostaticFilterMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeElectrostaticFilterMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadElectrostaticFilterMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeElectrostaticFilterMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadElectrostaticFilterMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeElectrostaticFilterMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadElectrostaticFilterMonitoringEventList : public ReadAttribute {
public:
    ReadElectrostaticFilterMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadElectrostaticFilterMonitoringEventList() {}

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

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

class SubscribeAttributeElectrostaticFilterMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeElectrostaticFilterMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeElectrostaticFilterMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadElectrostaticFilterMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeElectrostaticFilterMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadElectrostaticFilterMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeElectrostaticFilterMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadElectrostaticFilterMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeElectrostaticFilterMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster UvFilterMonitoring                                          | 0x0075 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class UvFilterMonitoringResetCondition : public ClusterCommand {
public:
    UvFilterMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterUVFilterMonitoring alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRUVFilterMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadUvFilterMonitoringCondition : public ReadAttribute {
public:
    ReadUvFilterMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadUvFilterMonitoringCondition() {}

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

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

class SubscribeAttributeUvFilterMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeUvFilterMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeUvFilterMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadUvFilterMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadUvFilterMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadUvFilterMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeUvFilterMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeUvFilterMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeUvFilterMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadUvFilterMonitoringChangeIndication : public ReadAttribute {
public:
    ReadUvFilterMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadUvFilterMonitoringChangeIndication() {}

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

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

class SubscribeAttributeUvFilterMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeUvFilterMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeUvFilterMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadUvFilterMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadUvFilterMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadUvFilterMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeUvFilterMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeUvFilterMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeUvFilterMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadUvFilterMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeUvFilterMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadUvFilterMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeUvFilterMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadUvFilterMonitoringEventList : public ReadAttribute {
public:
    ReadUvFilterMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadUvFilterMonitoringEventList() {}

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

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

class SubscribeAttributeUvFilterMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeUvFilterMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeUvFilterMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadUvFilterMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeUvFilterMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadUvFilterMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeUvFilterMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadUvFilterMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeUvFilterMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster IonizingFilterMonitoring                                    | 0x0076 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class IonizingFilterMonitoringResetCondition : public ClusterCommand {
public:
    IonizingFilterMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterIonizingFilterMonitoring alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRIonizingFilterMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadIonizingFilterMonitoringCondition : public ReadAttribute {
public:
    ReadIonizingFilterMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadIonizingFilterMonitoringCondition() {}

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

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

class SubscribeAttributeIonizingFilterMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeIonizingFilterMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeIonizingFilterMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadIonizingFilterMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadIonizingFilterMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadIonizingFilterMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeIonizingFilterMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeIonizingFilterMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeIonizingFilterMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadIonizingFilterMonitoringChangeIndication : public ReadAttribute {
public:
    ReadIonizingFilterMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadIonizingFilterMonitoringChangeIndication() {}

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

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

class SubscribeAttributeIonizingFilterMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeIonizingFilterMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeIonizingFilterMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadIonizingFilterMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadIonizingFilterMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadIonizingFilterMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeIonizingFilterMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeIonizingFilterMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeIonizingFilterMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIonizingFilterMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeIonizingFilterMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIonizingFilterMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeIonizingFilterMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadIonizingFilterMonitoringEventList : public ReadAttribute {
public:
    ReadIonizingFilterMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadIonizingFilterMonitoringEventList() {}

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

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

class SubscribeAttributeIonizingFilterMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeIonizingFilterMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeIonizingFilterMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIonizingFilterMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeIonizingFilterMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIonizingFilterMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeIonizingFilterMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIonizingFilterMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeIonizingFilterMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ZeoliteFilterMonitoring                                     | 0x0077 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class ZeoliteFilterMonitoringResetCondition : public ClusterCommand {
public:
    ZeoliteFilterMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterZeoliteFilterMonitoring alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRZeoliteFilterMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadZeoliteFilterMonitoringCondition : public ReadAttribute {
public:
    ReadZeoliteFilterMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadZeoliteFilterMonitoringCondition() {}

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

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

class SubscribeAttributeZeoliteFilterMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeZeoliteFilterMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeZeoliteFilterMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadZeoliteFilterMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadZeoliteFilterMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadZeoliteFilterMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeZeoliteFilterMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeZeoliteFilterMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeZeoliteFilterMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadZeoliteFilterMonitoringChangeIndication : public ReadAttribute {
public:
    ReadZeoliteFilterMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadZeoliteFilterMonitoringChangeIndication() {}

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

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

class SubscribeAttributeZeoliteFilterMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeZeoliteFilterMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeZeoliteFilterMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadZeoliteFilterMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadZeoliteFilterMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadZeoliteFilterMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeZeoliteFilterMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeZeoliteFilterMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeZeoliteFilterMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadZeoliteFilterMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeZeoliteFilterMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadZeoliteFilterMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeZeoliteFilterMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadZeoliteFilterMonitoringEventList : public ReadAttribute {
public:
    ReadZeoliteFilterMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadZeoliteFilterMonitoringEventList() {}

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

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

class SubscribeAttributeZeoliteFilterMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeZeoliteFilterMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeZeoliteFilterMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadZeoliteFilterMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeZeoliteFilterMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadZeoliteFilterMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeZeoliteFilterMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadZeoliteFilterMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeZeoliteFilterMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OzoneFilterMonitoring                                       | 0x0078 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class OzoneFilterMonitoringResetCondition : public ClusterCommand {
public:
    OzoneFilterMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterOzoneFilterMonitoring alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTROzoneFilterMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadOzoneFilterMonitoringCondition : public ReadAttribute {
public:
    ReadOzoneFilterMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadOzoneFilterMonitoringCondition() {}

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

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

class SubscribeAttributeOzoneFilterMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeOzoneFilterMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeOzoneFilterMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadOzoneFilterMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadOzoneFilterMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadOzoneFilterMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeOzoneFilterMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeOzoneFilterMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeOzoneFilterMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadOzoneFilterMonitoringChangeIndication : public ReadAttribute {
public:
    ReadOzoneFilterMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadOzoneFilterMonitoringChangeIndication() {}

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

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

class SubscribeAttributeOzoneFilterMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeOzoneFilterMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeOzoneFilterMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadOzoneFilterMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadOzoneFilterMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadOzoneFilterMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeOzoneFilterMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeOzoneFilterMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeOzoneFilterMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOzoneFilterMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeOzoneFilterMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOzoneFilterMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeOzoneFilterMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadOzoneFilterMonitoringEventList : public ReadAttribute {
public:
    ReadOzoneFilterMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadOzoneFilterMonitoringEventList() {}

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

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

class SubscribeAttributeOzoneFilterMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeOzoneFilterMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeOzoneFilterMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOzoneFilterMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeOzoneFilterMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOzoneFilterMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeOzoneFilterMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOzoneFilterMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeOzoneFilterMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster WaterTankMonitoring                                         | 0x0079 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class WaterTankMonitoringResetCondition : public ClusterCommand {
public:
    WaterTankMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterWaterTankMonitoring alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRWaterTankMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadWaterTankMonitoringCondition : public ReadAttribute {
public:
    ReadWaterTankMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadWaterTankMonitoringCondition() {}

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

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

class SubscribeAttributeWaterTankMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeWaterTankMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeWaterTankMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadWaterTankMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadWaterTankMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadWaterTankMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeWaterTankMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeWaterTankMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeWaterTankMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadWaterTankMonitoringChangeIndication : public ReadAttribute {
public:
    ReadWaterTankMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadWaterTankMonitoringChangeIndication() {}

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

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

class SubscribeAttributeWaterTankMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeWaterTankMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeWaterTankMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadWaterTankMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadWaterTankMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadWaterTankMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeWaterTankMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeWaterTankMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeWaterTankMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadWaterTankMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeWaterTankMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadWaterTankMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeWaterTankMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadWaterTankMonitoringEventList : public ReadAttribute {
public:
    ReadWaterTankMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadWaterTankMonitoringEventList() {}

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

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

class SubscribeAttributeWaterTankMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeWaterTankMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeWaterTankMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadWaterTankMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeWaterTankMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadWaterTankMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeWaterTankMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadWaterTankMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeWaterTankMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster FuelTankMonitoring                                          | 0x007A |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class FuelTankMonitoringResetCondition : public ClusterCommand {
public:
    FuelTankMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterFuelTankMonitoring alloc] initWithDevice:device
                                                                              endpointID:@(endpointId)
                                                                                   queue:callbackQueue];
        __auto_type * params = [[MTRFuelTankMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadFuelTankMonitoringCondition : public ReadAttribute {
public:
    ReadFuelTankMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadFuelTankMonitoringCondition() {}

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

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

class SubscribeAttributeFuelTankMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeFuelTankMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeFuelTankMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadFuelTankMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadFuelTankMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadFuelTankMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeFuelTankMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeFuelTankMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeFuelTankMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadFuelTankMonitoringChangeIndication : public ReadAttribute {
public:
    ReadFuelTankMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadFuelTankMonitoringChangeIndication() {}

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

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

class SubscribeAttributeFuelTankMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeFuelTankMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeFuelTankMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadFuelTankMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadFuelTankMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadFuelTankMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeFuelTankMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeFuelTankMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeFuelTankMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadFuelTankMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeFuelTankMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadFuelTankMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeFuelTankMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadFuelTankMonitoringEventList : public ReadAttribute {
public:
    ReadFuelTankMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadFuelTankMonitoringEventList() {}

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

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

class SubscribeAttributeFuelTankMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeFuelTankMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeFuelTankMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadFuelTankMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeFuelTankMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadFuelTankMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeFuelTankMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadFuelTankMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeFuelTankMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster InkCartridgeMonitoring                                      | 0x007B |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class InkCartridgeMonitoringResetCondition : public ClusterCommand {
public:
    InkCartridgeMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterInkCartridgeMonitoring alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRInkCartridgeMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadInkCartridgeMonitoringCondition : public ReadAttribute {
public:
    ReadInkCartridgeMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadInkCartridgeMonitoringCondition() {}

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

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

class SubscribeAttributeInkCartridgeMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeInkCartridgeMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeInkCartridgeMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadInkCartridgeMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadInkCartridgeMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadInkCartridgeMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeInkCartridgeMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeInkCartridgeMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeInkCartridgeMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadInkCartridgeMonitoringChangeIndication : public ReadAttribute {
public:
    ReadInkCartridgeMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadInkCartridgeMonitoringChangeIndication() {}

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

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

class SubscribeAttributeInkCartridgeMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeInkCartridgeMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeInkCartridgeMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadInkCartridgeMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadInkCartridgeMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadInkCartridgeMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeInkCartridgeMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeInkCartridgeMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeInkCartridgeMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadInkCartridgeMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeInkCartridgeMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadInkCartridgeMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeInkCartridgeMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadInkCartridgeMonitoringEventList : public ReadAttribute {
public:
    ReadInkCartridgeMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadInkCartridgeMonitoringEventList() {}

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

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

class SubscribeAttributeInkCartridgeMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeInkCartridgeMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeInkCartridgeMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadInkCartridgeMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeInkCartridgeMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadInkCartridgeMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeInkCartridgeMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadInkCartridgeMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeInkCartridgeMonitoringClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster TonerCartridgeMonitoring                                    | 0x007C |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCondition                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Condition                                                         | 0x0000 |
| * DegradationDirection                                              | 0x0001 |
| * ChangeIndication                                                  | 0x0002 |
| * InPlaceIndicator                                                  | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCondition
 */
class TonerCartridgeMonitoringResetCondition : public ClusterCommand {
public:
    TonerCartridgeMonitoringResetCondition()
        : ClusterCommand("reset-condition")
    {
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterTonerCartridgeMonitoring alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRTonerCartridgeMonitoringClusterResetConditionParams 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 resetConditionWithParams: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 Condition
 */
class ReadTonerCartridgeMonitoringCondition : public ReadAttribute {
public:
    ReadTonerCartridgeMonitoringCondition()
        : ReadAttribute("condition")
    {
    }

    ~ReadTonerCartridgeMonitoringCondition() {}

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

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

class SubscribeAttributeTonerCartridgeMonitoringCondition : public SubscribeAttribute {
public:
    SubscribeAttributeTonerCartridgeMonitoringCondition()
        : SubscribeAttribute("condition")
    {
    }

    ~SubscribeAttributeTonerCartridgeMonitoringCondition() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DegradationDirection
 */
class ReadTonerCartridgeMonitoringDegradationDirection : public ReadAttribute {
public:
    ReadTonerCartridgeMonitoringDegradationDirection()
        : ReadAttribute("degradation-direction")
    {
    }

    ~ReadTonerCartridgeMonitoringDegradationDirection() {}

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

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

class SubscribeAttributeTonerCartridgeMonitoringDegradationDirection : public SubscribeAttribute {
public:
    SubscribeAttributeTonerCartridgeMonitoringDegradationDirection()
        : SubscribeAttribute("degradation-direction")
    {
    }

    ~SubscribeAttributeTonerCartridgeMonitoringDegradationDirection() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChangeIndication
 */
class ReadTonerCartridgeMonitoringChangeIndication : public ReadAttribute {
public:
    ReadTonerCartridgeMonitoringChangeIndication()
        : ReadAttribute("change-indication")
    {
    }

    ~ReadTonerCartridgeMonitoringChangeIndication() {}

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

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

class SubscribeAttributeTonerCartridgeMonitoringChangeIndication : public SubscribeAttribute {
public:
    SubscribeAttributeTonerCartridgeMonitoringChangeIndication()
        : SubscribeAttribute("change-indication")
    {
    }

    ~SubscribeAttributeTonerCartridgeMonitoringChangeIndication() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InPlaceIndicator
 */
class ReadTonerCartridgeMonitoringInPlaceIndicator : public ReadAttribute {
public:
    ReadTonerCartridgeMonitoringInPlaceIndicator()
        : ReadAttribute("in-place-indicator")
    {
    }

    ~ReadTonerCartridgeMonitoringInPlaceIndicator() {}

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

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

class SubscribeAttributeTonerCartridgeMonitoringInPlaceIndicator : public SubscribeAttribute {
public:
    SubscribeAttributeTonerCartridgeMonitoringInPlaceIndicator()
        : SubscribeAttribute("in-place-indicator")
    {
    }

    ~SubscribeAttributeTonerCartridgeMonitoringInPlaceIndicator() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadTonerCartridgeMonitoringGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeTonerCartridgeMonitoringGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadTonerCartridgeMonitoringAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeTonerCartridgeMonitoringAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadTonerCartridgeMonitoringEventList : public ReadAttribute {
public:
    ReadTonerCartridgeMonitoringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadTonerCartridgeMonitoringEventList() {}

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

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

class SubscribeAttributeTonerCartridgeMonitoringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeTonerCartridgeMonitoringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeTonerCartridgeMonitoringEventList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadTonerCartridgeMonitoringAttributeList() {}

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

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

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

    ~SubscribeAttributeTonerCartridgeMonitoringAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadTonerCartridgeMonitoringFeatureMap() {}

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

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

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

    ~SubscribeAttributeTonerCartridgeMonitoringFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadTonerCartridgeMonitoringClusterRevision() {}

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

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

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

    ~SubscribeAttributeTonerCartridgeMonitoringClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000007C) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterTonerCartridgeMonitoring alloc] initWithDevice:device
                                                                                    endpointID:@(endpointId)
                                                                                         queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TonerCartridgeMonitoring.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 |
| * UnboltDoor                                                        |   0x27 |
|------------------------------------------------------------------------------|
| 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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 = [MTRDoorLockClusterCredentialStruct 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::CredentialStruct::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);
        __auto_type * 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 = [MTRDoorLockClusterCredentialStruct 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::CredentialStruct::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);
        __auto_type * 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 = [MTRDoorLockClusterCredentialStruct 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::CredentialStruct::Type>>
        mComplex_Credential;
};

/*
 * Command UnboltDoor
 */
class DoorLockUnboltDoor : public ClusterCommand {
public:
    DoorLockUnboltDoor()
        : ClusterCommand("unbolt-door")
    {
        AddArgument("PINCode", &mRequest.PINCode);
        ClusterCommand::AddArguments();
    }

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterUnboltDoorParams 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 unboltDoorWithParams: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::UnboltDoor::Type mRequest;
};

/*
 * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadDoorLockEventList : public ReadAttribute {
public:
    ReadDoorLockEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadDoorLockEventList() {}

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

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

class SubscribeAttributeDoorLockEventList : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeDoorLockEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadWindowCoveringEventList : public ReadAttribute {
public:
    ReadWindowCoveringEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadWindowCoveringEventList() {}

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

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

class SubscribeAttributeWindowCoveringEventList : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeWindowCoveringEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadBarrierControlEventList : public ReadAttribute {
public:
    ReadBarrierControlEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadBarrierControlEventList() {}

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

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

class SubscribeAttributeBarrierControlEventList : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeBarrierControlEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                          endpointID:@(endpointId)
                                                                               queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadPumpConfigurationAndControlEventList : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadPumpConfigurationAndControlEventList() {}

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

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

class SubscribeAttributePumpConfigurationAndControlEventList : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadThermostatEventList : public ReadAttribute {
public:
    ReadThermostatEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadThermostatEventList() {}

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

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

class SubscribeAttributeThermostatEventList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeThermostatEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadFanControlEventList : public ReadAttribute {
public:
    ReadFanControlEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadFanControlEventList() {}

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

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

class SubscribeAttributeFanControlEventList : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeFanControlEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadThermostatUserInterfaceConfigurationEventList : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationEventList() {}

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

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

class SubscribeAttributeThermostatUserInterfaceConfigurationEventList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                                                endpointID:@(endpointId)
                                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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("ColorTemperatureMireds", 0, UINT16_MAX, &mRequest.colorTemperatureMireds);
        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);
        __auto_type * 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.colorTemperatureMireds = [NSNumber numberWithUnsignedShort:mRequest.colorTemperatureMireds];
        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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadColorControlEventList : public ReadAttribute {
public:
    ReadColorControlEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadColorControlEventList() {}

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

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

class SubscribeAttributeColorControlEventList : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeColorControlEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * IntrinsicBallastFactor                                            | 0x0014 |
| * BallastFactorAdjustment                                           | 0x0015 |
| * LampQuantity                                                      | 0x0020 |
| * LampType                                                          | 0x0030 |
| * LampManufacturer                                                  | 0x0031 |
| * LampRatedHours                                                    | 0x0032 |
| * LampBurnHours                                                     | 0x0033 |
| * LampAlarmMode                                                     | 0x0034 |
| * LampBurnHoursTripPoint                                            | 0x0035 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 IntrinsicBallastFactor
 */
class ReadBallastConfigurationIntrinsicBallastFactor : public ReadAttribute {
public:
    ReadBallastConfigurationIntrinsicBallastFactor()
        : ReadAttribute("intrinsic-ballast-factor")
    {
    }

    ~ReadBallastConfigurationIntrinsicBallastFactor() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        [cluster readAttributeIntrinsicBallastFactorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.IntrinsicBallastFactor response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration IntrinsicBallastFactor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationIntrinsicBallastFactor : public WriteAttribute {
public:
    WriteBallastConfigurationIntrinsicBallastFactor()
        : WriteAttribute("intrinsic-ballast-factor")
    {
        AddArgument("attr-name", "intrinsic-ballast-factor");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationIntrinsicBallastFactor() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

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

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationIntrinsicBallastFactor : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationIntrinsicBallastFactor()
        : SubscribeAttribute("intrinsic-ballast-factor")
    {
    }

    ~SubscribeAttributeBallastConfigurationIntrinsicBallastFactor() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeIntrinsicBallastFactorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.IntrinsicBallastFactor 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadBallastConfigurationEventList : public ReadAttribute {
public:
    ReadBallastConfigurationEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadBallastConfigurationEventList() {}

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationEventList : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeBallastConfigurationEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                endpointID:@(endpointId)
                                                                                     queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadIlluminanceMeasurementEventList : public ReadAttribute {
public:
    ReadIlluminanceMeasurementEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadIlluminanceMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementEventList : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadTemperatureMeasurementEventList : public ReadAttribute {
public:
    ReadTemperatureMeasurementEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadTemperatureMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementEventList : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device
                                                                                  endpointID:@(endpointId)
                                                                                       queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadPressureMeasurementEventList : public ReadAttribute {
public:
    ReadPressureMeasurementEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadPressureMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementEventList : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributePressureMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadFlowMeasurementEventList : public ReadAttribute {
public:
    ReadFlowMeasurementEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadFlowMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementEventList : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeFlowMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadRelativeHumidityMeasurementEventList : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadRelativeHumidityMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementEventList : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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("piroccupied-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);
        __auto_type * 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("piroccupied-to-unoccupied-delay")
    {
        AddArgument("attr-name", "piroccupied-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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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("piroccupied-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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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("pirunoccupied-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);
        __auto_type * 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("pirunoccupied-to-occupied-delay")
    {
        AddArgument("attr-name", "pirunoccupied-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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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("pirunoccupied-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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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("pirunoccupied-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);
        __auto_type * 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("pirunoccupied-to-occupied-threshold")
    {
        AddArgument("attr-name", "pirunoccupied-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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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("pirunoccupied-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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadOccupancySensingEventList : public ReadAttribute {
public:
    ReadOccupancySensingEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadOccupancySensingEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingEventList : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeOccupancySensingEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWakeOnLAN alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWakeOnLAN alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWakeOnLAN alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadWakeOnLanEventList : public ReadAttribute {
public:
    ReadWakeOnLanEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadWakeOnLanEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterWakeOnLAN alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLAN.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLAN EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanEventList : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeWakeOnLanEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterWakeOnLAN alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLAN.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWakeOnLAN alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWakeOnLAN alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterWakeOnLAN alloc] initWithDevice:device
                                                                     endpointID:@(endpointId)
                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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", INT16_MIN, INT16_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);
        __auto_type * 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 numberWithShort: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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster
            readAttributeLineupWithCompletion:^(MTRChannelClusterLineupInfoStruct * _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);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeLineupWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRChannelClusterLineupInfoStruct * _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);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeCurrentChannelWithCompletion:^(
            MTRChannelClusterChannelInfoStruct * _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);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeCurrentChannelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRChannelClusterChannelInfoStruct * _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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadChannelEventList : public ReadAttribute {
public:
    ReadChannelEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadChannelEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelEventList : public SubscribeAttribute {
public:
    SubscribeAttributeChannelEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeChannelEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadTargetNavigatorEventList : public ReadAttribute {
public:
    ReadTargetNavigatorEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadTargetNavigatorEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorEventList : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeTargetNavigatorEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * Stop                                                              |   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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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 Stop
 */
class MediaPlaybackStop : public ClusterCommand {
public:
    MediaPlaybackStop()
        : ClusterCommand("stop")
    {
        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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterStopParams 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 stopWithParams: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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeSampledPositionWithCompletion:^(
            MTRMediaPlaybackClusterPlaybackPositionStruct * _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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeSampledPositionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRMediaPlaybackClusterPlaybackPositionStruct * _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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadMediaPlaybackEventList : public ReadAttribute {
public:
    ReadMediaPlaybackEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadMediaPlaybackEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackEventList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeMediaPlaybackEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadMediaInputEventList : public ReadAttribute {
public:
    ReadMediaInputEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadMediaInputEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputEventList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeMediaInputEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                      endpointID:@(endpointId)
                                                                           queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadLowPowerEventList : public ReadAttribute {
public:
    ReadLowPowerEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadLowPowerEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerEventList : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeLowPowerEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadKeypadInputEventList : public ReadAttribute {
public:
    ReadKeypadInputEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadKeypadInputEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputEventList : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeKeypadInputEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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 = [MTRContentLauncherClusterContentSearchStruct new];
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.search.parameterList) {
                MTRContentLauncherClusterParameterStruct * newElement_1;
                newElement_1 = [MTRContentLauncherClusterParameterStruct 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()) {
                            MTRContentLauncherClusterAdditionalInfoStruct * newElement_4;
                            newElement_4 = [MTRContentLauncherClusterAdditionalInfoStruct 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:^(MTRContentLauncherClusterLauncherResponseParams * _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::ContentSearchStruct::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);
        __auto_type * 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 = [MTRContentLauncherClusterBrandingInformationStruct 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 = [MTRContentLauncherClusterStyleInformationStruct 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 = [MTRContentLauncherClusterDimensionStruct 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 = [MTRContentLauncherClusterStyleInformationStruct 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 = [MTRContentLauncherClusterDimensionStruct 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 = [MTRContentLauncherClusterStyleInformationStruct 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 = [MTRContentLauncherClusterDimensionStruct 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 = [MTRContentLauncherClusterStyleInformationStruct 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 = [MTRContentLauncherClusterDimensionStruct 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 = [MTRContentLauncherClusterStyleInformationStruct 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 = [MTRContentLauncherClusterDimensionStruct 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:^(
                                  MTRContentLauncherClusterLauncherResponseParams * _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::BrandingInformationStruct::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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadContentLauncherEventList : public ReadAttribute {
public:
    ReadContentLauncherEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadContentLauncherEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherEventList : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeContentLauncherEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadAudioOutputEventList : public ReadAttribute {
public:
    ReadAudioOutputEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadAudioOutputEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputEventList : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeAudioOutputEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRApplicationLauncherClusterLaunchAppParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.application.HasValue()) {
            params.application = [MTRApplicationLauncherClusterApplicationStruct new];
            params.application.catalogVendorID = [NSNumber numberWithUnsignedShort:mRequest.application.Value().catalogVendorID];
            params.application.applicationID = [[NSString alloc] initWithBytes:mRequest.application.Value().applicationID.data()
                                                                        length:mRequest.application.Value().applicationID.size()
                                                                      encoding:NSUTF8StringEncoding];
        } else {
            params.application = nil;
        }
        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::Optional<chip::app::Clusters::ApplicationLauncher::Structs::ApplicationStruct::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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRApplicationLauncherClusterStopAppParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.application.HasValue()) {
            params.application = [MTRApplicationLauncherClusterApplicationStruct new];
            params.application.catalogVendorID = [NSNumber numberWithUnsignedShort:mRequest.application.Value().catalogVendorID];
            params.application.applicationID = [[NSString alloc] initWithBytes:mRequest.application.Value().applicationID.data()
                                                                        length:mRequest.application.Value().applicationID.size()
                                                                      encoding:NSUTF8StringEncoding];
        } else {
            params.application = nil;
        }
        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::Optional<chip::app::Clusters::ApplicationLauncher::Structs::ApplicationStruct::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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRApplicationLauncherClusterHideAppParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.application.HasValue()) {
            params.application = [MTRApplicationLauncherClusterApplicationStruct new];
            params.application.catalogVendorID = [NSNumber numberWithUnsignedShort:mRequest.application.Value().catalogVendorID];
            params.application.applicationID = [[NSString alloc] initWithBytes:mRequest.application.Value().applicationID.data()
                                                                        length:mRequest.application.Value().applicationID.size()
                                                                      encoding:NSUTF8StringEncoding];
        } else {
            params.application = nil;
        }
        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::Optional<chip::app::Clusters::ApplicationLauncher::Structs::ApplicationStruct::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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeCurrentAppWithCompletion:^(
            MTRApplicationLauncherClusterApplicationEPStruct * _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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        MTRApplicationLauncherClusterApplicationEPStruct * _Nullable value;
        if (mValue.IsNull()) {
            value = nil;
        } else {
            value = [MTRApplicationLauncherClusterApplicationEPStruct new];
            value.application = [MTRApplicationLauncherClusterApplicationStruct 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::ApplicationEPStruct::Type> mValue;
    TypedComplexArgument<
        chip::app::DataModel::Nullable<chip::app::Clusters::ApplicationLauncher::Structs::ApplicationEPStruct::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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeCurrentAppWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRApplicationLauncherClusterApplicationEPStruct * _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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadApplicationLauncherEventList : public ReadAttribute {
public:
    ReadApplicationLauncherEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadApplicationLauncherEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherEventList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeApplicationLauncherEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeApplicationWithCompletion:^(
            MTRApplicationBasicClusterApplicationStruct * _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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeApplicationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRApplicationBasicClusterApplicationStruct * _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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadApplicationBasicEventList : public ReadAttribute {
public:
    ReadApplicationBasicEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadApplicationBasicEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicEventList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeApplicationBasicEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadAccountLoginEventList : public ReadAttribute {
public:
    ReadAccountLoginEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadAccountLoginEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginEventList : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeAccountLoginEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                        endpointID:@(endpointId)
                                                                             queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 |
| * EventList                                                         | 0xFFFA |
| * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 EventList
 */
class ReadElectricalMeasurementEventList : public ReadAttribute {
public:
    ReadElectricalMeasurementEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadElectricalMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementEventList : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeElectricalMeasurementEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.EventList 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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);
        __auto_type * 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);
        __auto_type * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster 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 UnitTesting                                                 | 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 |
| * EventList                                                         | 0xFFFA |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * TestEvent                                                         | 0x0001 |
| * TestFabricScopedEvent                                             | 0x0002 |
\*----------------------------------------------------------------------------*/

/*
 * Command Test
 */
class UnitTestingTest : public ClusterCommand {
public:
    UnitTestingTest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestParams 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 UnitTestingTestNotHandled : public ClusterCommand {
public:
    UnitTestingTestNotHandled()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestNotHandledParams 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 UnitTestingTestSpecific : public ClusterCommand {
public:
    UnitTestingTestSpecific()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestSpecificParams 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:^(MTRUnitTestingClusterTestSpecificResponseParams * _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 UnitTestingTestUnknownCommand : public ClusterCommand {
public:
    UnitTestingTestUnknownCommand()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestUnknownCommandParams 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 UnitTestingTestAddArguments : public ClusterCommand {
public:
    UnitTestingTestAddArguments()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestAddArgumentsParams 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:^(MTRUnitTestingClusterTestAddArgumentsResponseParams * _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::UnitTesting::Commands::TestAddArguments::Type mRequest;
};

/*
 * Command TestSimpleArgumentRequest
 */
class UnitTestingTestSimpleArgumentRequest : public ClusterCommand {
public:
    UnitTestingTestSimpleArgumentRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestSimpleArgumentRequestParams 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:^(MTRUnitTestingClusterTestSimpleArgumentResponseParams * _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::UnitTesting::Commands::TestSimpleArgumentRequest::Type mRequest;
};

/*
 * Command TestStructArrayArgumentRequest
 */
class UnitTestingTestStructArrayArgumentRequest : public ClusterCommand {
public:
    UnitTestingTestStructArrayArgumentRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestStructArrayArgumentRequestParams 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) {
                MTRUnitTestingClusterNestedStructList * newElement_0;
                newElement_0 = [MTRUnitTestingClusterNestedStructList new];
                newElement_0.a = [NSNumber numberWithUnsignedChar:entry_0.a];
                newElement_0.b = [NSNumber numberWithBool:entry_0.b];
                newElement_0.c = [MTRUnitTestingClusterSimpleStruct 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) {
                        MTRUnitTestingClusterSimpleStruct * newElement_2;
                        newElement_2 = [MTRUnitTestingClusterSimpleStruct 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) {
                MTRUnitTestingClusterSimpleStruct * newElement_0;
                newElement_0 = [MTRUnitTestingClusterSimpleStruct 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:^(
                                                  MTRUnitTestingClusterTestStructArrayArgumentResponseParams * _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::UnitTesting::Commands::TestStructArrayArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::Structs::NestedStructList::Type>>
        mComplex_Arg1;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type>>
        mComplex_Arg2;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::SimpleEnum>> mComplex_Arg3;
    TypedComplexArgument<chip::app::DataModel::List<const bool>> mComplex_Arg4;
};

/*
 * Command TestStructArgumentRequest
 */
class UnitTestingTestStructArgumentRequest : public ClusterCommand {
public:
    UnitTestingTestStructArgumentRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestStructArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRUnitTestingClusterSimpleStruct 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:^(MTRUnitTestingClusterBooleanResponseParams * _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::UnitTesting::Commands::TestStructArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type> mComplex_Arg1;
};

/*
 * Command TestNestedStructArgumentRequest
 */
class UnitTestingTestNestedStructArgumentRequest : public ClusterCommand {
public:
    UnitTestingTestNestedStructArgumentRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestNestedStructArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRUnitTestingClusterNestedStruct new];
        params.arg1.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.a];
        params.arg1.b = [NSNumber numberWithBool:mRequest.arg1.b];
        params.arg1.c = [MTRUnitTestingClusterSimpleStruct 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:^(MTRUnitTestingClusterBooleanResponseParams * _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::UnitTesting::Commands::TestNestedStructArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::UnitTesting::Structs::NestedStruct::Type> mComplex_Arg1;
};

/*
 * Command TestListStructArgumentRequest
 */
class UnitTestingTestListStructArgumentRequest : public ClusterCommand {
public:
    UnitTestingTestListStructArgumentRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestListStructArgumentRequestParams 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) {
                MTRUnitTestingClusterSimpleStruct * newElement_0;
                newElement_0 = [MTRUnitTestingClusterSimpleStruct 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:^(MTRUnitTestingClusterBooleanResponseParams * _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::UnitTesting::Commands::TestListStructArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type>>
        mComplex_Arg1;
};

/*
 * Command TestListInt8UArgumentRequest
 */
class UnitTestingTestListInt8UArgumentRequest : public ClusterCommand {
public:
    UnitTestingTestListInt8UArgumentRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestListInt8UArgumentRequestParams 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:^(MTRUnitTestingClusterBooleanResponseParams * _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::UnitTesting::Commands::TestListInt8UArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const uint8_t>> mComplex_Arg1;
};

/*
 * Command TestNestedStructListArgumentRequest
 */
class UnitTestingTestNestedStructListArgumentRequest : public ClusterCommand {
public:
    UnitTestingTestNestedStructListArgumentRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestNestedStructListArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRUnitTestingClusterNestedStructList new];
        params.arg1.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.a];
        params.arg1.b = [NSNumber numberWithBool:mRequest.arg1.b];
        params.arg1.c = [MTRUnitTestingClusterSimpleStruct 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) {
                MTRUnitTestingClusterSimpleStruct * newElement_1;
                newElement_1 = [MTRUnitTestingClusterSimpleStruct 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:^(MTRUnitTestingClusterBooleanResponseParams * _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::UnitTesting::Commands::TestNestedStructListArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::UnitTesting::Structs::NestedStructList::Type> mComplex_Arg1;
};

/*
 * Command TestListNestedStructListArgumentRequest
 */
class UnitTestingTestListNestedStructListArgumentRequest : public ClusterCommand {
public:
    UnitTestingTestListNestedStructListArgumentRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestListNestedStructListArgumentRequestParams 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) {
                MTRUnitTestingClusterNestedStructList * newElement_0;
                newElement_0 = [MTRUnitTestingClusterNestedStructList new];
                newElement_0.a = [NSNumber numberWithUnsignedChar:entry_0.a];
                newElement_0.b = [NSNumber numberWithBool:entry_0.b];
                newElement_0.c = [MTRUnitTestingClusterSimpleStruct 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) {
                        MTRUnitTestingClusterSimpleStruct * newElement_2;
                        newElement_2 = [MTRUnitTestingClusterSimpleStruct 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:^(MTRUnitTestingClusterBooleanResponseParams * _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::UnitTesting::Commands::TestListNestedStructListArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::Structs::NestedStructList::Type>>
        mComplex_Arg1;
};

/*
 * Command TestListInt8UReverseRequest
 */
class UnitTestingTestListInt8UReverseRequest : public ClusterCommand {
public:
    UnitTestingTestListInt8UReverseRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestListInt8UReverseRequestParams 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:^(MTRUnitTestingClusterTestListInt8UReverseResponseParams * _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::UnitTesting::Commands::TestListInt8UReverseRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const uint8_t>> mComplex_Arg1;
};

/*
 * Command TestEnumsRequest
 */
class UnitTestingTestEnumsRequest : public ClusterCommand {
public:
    UnitTestingTestEnumsRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestEnumsRequestParams 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:^(MTRUnitTestingClusterTestEnumsResponseParams * _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::UnitTesting::Commands::TestEnumsRequest::Type mRequest;
};

/*
 * Command TestNullableOptionalRequest
 */
class UnitTestingTestNullableOptionalRequest : public ClusterCommand {
public:
    UnitTestingTestNullableOptionalRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestNullableOptionalRequestParams 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:^(MTRUnitTestingClusterTestNullableOptionalResponseParams * _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::UnitTesting::Commands::TestNullableOptionalRequest::Type mRequest;
};

/*
 * Command TestComplexNullableOptionalRequest
 */
class UnitTestingTestComplexNullableOptionalRequest : public ClusterCommand {
public:
    UnitTestingTestComplexNullableOptionalRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestComplexNullableOptionalRequestParams 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 = [MTRUnitTestingClusterSimpleStruct 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 = [MTRUnitTestingClusterSimpleStruct 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 = [MTRUnitTestingClusterSimpleStruct 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:^(
                                                      MTRUnitTestingClusterTestComplexNullableOptionalResponseParams * _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::UnitTesting::Commands::TestComplexNullableOptionalRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::Nullable<chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type>>
        mComplex_NullableStruct;
    TypedComplexArgument<chip::Optional<chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type>> mComplex_OptionalStruct;
    TypedComplexArgument<
        chip::Optional<chip::app::DataModel::Nullable<chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type>>>
        mComplex_NullableOptionalStruct;
    TypedComplexArgument<
        chip::app::DataModel::Nullable<chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::SimpleEnum>>>
        mComplex_NullableList;
    TypedComplexArgument<chip::Optional<chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::SimpleEnum>>>
        mComplex_OptionalList;
    TypedComplexArgument<chip::Optional<
        chip::app::DataModel::Nullable<chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::SimpleEnum>>>>
        mComplex_NullableOptionalList;
};

/*
 * Command SimpleStructEchoRequest
 */
class UnitTestingSimpleStructEchoRequest : public ClusterCommand {
public:
    UnitTestingSimpleStructEchoRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterSimpleStructEchoRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRUnitTestingClusterSimpleStruct 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:^(MTRUnitTestingClusterSimpleStructResponseParams * _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::UnitTesting::Commands::SimpleStructEchoRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type> mComplex_Arg1;
};

/*
 * Command TimedInvokeRequest
 */
class UnitTestingTimedInvokeRequest : public ClusterCommand {
public:
    UnitTestingTimedInvokeRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTimedInvokeRequestParams 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 UnitTestingTestSimpleOptionalArgumentRequest : public ClusterCommand {
public:
    UnitTestingTestSimpleOptionalArgumentRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestSimpleOptionalArgumentRequestParams 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::UnitTesting::Commands::TestSimpleOptionalArgumentRequest::Type mRequest;
};

/*
 * Command TestEmitTestEventRequest
 */
class UnitTestingTestEmitTestEventRequest : public ClusterCommand {
public:
    UnitTestingTestEmitTestEventRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestEmitTestEventRequestParams 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:^(MTRUnitTestingClusterTestEmitTestEventResponseParams * _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::UnitTesting::Commands::TestEmitTestEventRequest::Type mRequest;
};

/*
 * Command TestEmitTestFabricScopedEventRequest
 */
class UnitTestingTestEmitTestFabricScopedEventRequest : public ClusterCommand {
public:
    UnitTestingTestEmitTestFabricScopedEventRequest()
        : 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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRUnitTestingClusterTestEmitTestFabricScopedEventRequestParams 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:^(
                                                        MTRUnitTestingClusterTestEmitTestFabricScopedEventResponseParams * _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::UnitTesting::Commands::TestEmitTestFabricScopedEventRequest::Type mRequest;
};

/*
 * Attribute Boolean
 */
class ReadUnitTestingBoolean : public ReadAttribute {
public:
    ReadUnitTestingBoolean()
        : ReadAttribute("boolean")
    {
    }

    ~ReadUnitTestingBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeBooleanWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Boolean response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Boolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingBoolean : public WriteAttribute {
public:
    WriteUnitTestingBoolean()
        : WriteAttribute("boolean")
    {
        AddArgument("attr-name", "boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeBooleanWithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("UnitTesting Boolean write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeUnitTestingBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingBoolean()
        : SubscribeAttribute("boolean")
    {
    }

    ~SubscribeAttributeUnitTestingBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeBooleanWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Boolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap8
 */
class ReadUnitTestingBitmap8 : public ReadAttribute {
public:
    ReadUnitTestingBitmap8()
        : ReadAttribute("bitmap8")
    {
    }

    ~ReadUnitTestingBitmap8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeBitmap8WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Bitmap8 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Bitmap8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingBitmap8 : public WriteAttribute {
public:
    WriteUnitTestingBitmap8()
        : WriteAttribute("bitmap8")
    {
        AddArgument("attr-name", "bitmap8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingBitmap8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeBitmap8WithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("UnitTesting Bitmap8 write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingBitmap8 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingBitmap8()
        : SubscribeAttribute("bitmap8")
    {
    }

    ~SubscribeAttributeUnitTestingBitmap8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeBitmap8WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Bitmap8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap16
 */
class ReadUnitTestingBitmap16 : public ReadAttribute {
public:
    ReadUnitTestingBitmap16()
        : ReadAttribute("bitmap16")
    {
    }

    ~ReadUnitTestingBitmap16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeBitmap16WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Bitmap16 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Bitmap16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingBitmap16 : public WriteAttribute {
public:
    WriteUnitTestingBitmap16()
        : WriteAttribute("bitmap16")
    {
        AddArgument("attr-name", "bitmap16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingBitmap16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBitmap16WithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("UnitTesting Bitmap16 write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeUnitTestingBitmap16 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingBitmap16()
        : SubscribeAttribute("bitmap16")
    {
    }

    ~SubscribeAttributeUnitTestingBitmap16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeBitmap16WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Bitmap16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap32
 */
class ReadUnitTestingBitmap32 : public ReadAttribute {
public:
    ReadUnitTestingBitmap32()
        : ReadAttribute("bitmap32")
    {
    }

    ~ReadUnitTestingBitmap32() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeBitmap32WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Bitmap32 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Bitmap32 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingBitmap32 : public WriteAttribute {
public:
    WriteUnitTestingBitmap32()
        : WriteAttribute("bitmap32")
    {
        AddArgument("attr-name", "bitmap32");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingBitmap32() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeBitmap32WithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("UnitTesting Bitmap32 write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeUnitTestingBitmap32 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingBitmap32()
        : SubscribeAttribute("bitmap32")
    {
    }

    ~SubscribeAttributeUnitTestingBitmap32() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeBitmap32WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Bitmap32 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap64
 */
class ReadUnitTestingBitmap64 : public ReadAttribute {
public:
    ReadUnitTestingBitmap64()
        : ReadAttribute("bitmap64")
    {
    }

    ~ReadUnitTestingBitmap64() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeBitmap64WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Bitmap64 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Bitmap64 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingBitmap64 : public WriteAttribute {
public:
    WriteUnitTestingBitmap64()
        : WriteAttribute("bitmap64")
    {
        AddArgument("attr-name", "bitmap64");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingBitmap64() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeBitmap64WithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("UnitTesting Bitmap64 write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingBitmap64 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingBitmap64()
        : SubscribeAttribute("bitmap64")
    {
    }

    ~SubscribeAttributeUnitTestingBitmap64() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeBitmap64WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Bitmap64 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int8u
 */
class ReadUnitTestingInt8u : public ReadAttribute {
public:
    ReadUnitTestingInt8u()
        : ReadAttribute("int8u")
    {
    }

    ~ReadUnitTestingInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int8u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt8u : public WriteAttribute {
public:
    WriteUnitTestingInt8u()
        : WriteAttribute("int8u")
    {
        AddArgument("attr-name", "int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeInt8uWithValue:value
                                       params:params
                                   completion:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("UnitTesting Int8u write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt8u()
        : SubscribeAttribute("int8u")
    {
    }

    ~SubscribeAttributeUnitTestingInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int16u
 */
class ReadUnitTestingInt16u : public ReadAttribute {
public:
    ReadUnitTestingInt16u()
        : ReadAttribute("int16u")
    {
    }

    ~ReadUnitTestingInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt16uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int16u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt16u : public WriteAttribute {
public:
    WriteUnitTestingInt16u()
        : WriteAttribute("int16u")
    {
        AddArgument("attr-name", "int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeInt16uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int16u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeUnitTestingInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt16u()
        : SubscribeAttribute("int16u")
    {
    }

    ~SubscribeAttributeUnitTestingInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt16uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int24u
 */
class ReadUnitTestingInt24u : public ReadAttribute {
public:
    ReadUnitTestingInt24u()
        : ReadAttribute("int24u")
    {
    }

    ~ReadUnitTestingInt24u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt24uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int24u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int24u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt24u : public WriteAttribute {
public:
    WriteUnitTestingInt24u()
        : WriteAttribute("int24u")
    {
        AddArgument("attr-name", "int24u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt24u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeInt24uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int24u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeUnitTestingInt24u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt24u()
        : SubscribeAttribute("int24u")
    {
    }

    ~SubscribeAttributeUnitTestingInt24u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt24uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int24u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int32u
 */
class ReadUnitTestingInt32u : public ReadAttribute {
public:
    ReadUnitTestingInt32u()
        : ReadAttribute("int32u")
    {
    }

    ~ReadUnitTestingInt32u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt32uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int32u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int32u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt32u : public WriteAttribute {
public:
    WriteUnitTestingInt32u()
        : WriteAttribute("int32u")
    {
        AddArgument("attr-name", "int32u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt32u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeInt32uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int32u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeUnitTestingInt32u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt32u()
        : SubscribeAttribute("int32u")
    {
    }

    ~SubscribeAttributeUnitTestingInt32u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt32uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int32u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int40u
 */
class ReadUnitTestingInt40u : public ReadAttribute {
public:
    ReadUnitTestingInt40u()
        : ReadAttribute("int40u")
    {
    }

    ~ReadUnitTestingInt40u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt40uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int40u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int40u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt40u : public WriteAttribute {
public:
    WriteUnitTestingInt40u()
        : WriteAttribute("int40u")
    {
        AddArgument("attr-name", "int40u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt40u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt40uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int40u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingInt40u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt40u()
        : SubscribeAttribute("int40u")
    {
    }

    ~SubscribeAttributeUnitTestingInt40u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt40uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int40u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int48u
 */
class ReadUnitTestingInt48u : public ReadAttribute {
public:
    ReadUnitTestingInt48u()
        : ReadAttribute("int48u")
    {
    }

    ~ReadUnitTestingInt48u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt48uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int48u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int48u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt48u : public WriteAttribute {
public:
    WriteUnitTestingInt48u()
        : WriteAttribute("int48u")
    {
        AddArgument("attr-name", "int48u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt48u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt48uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int48u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingInt48u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt48u()
        : SubscribeAttribute("int48u")
    {
    }

    ~SubscribeAttributeUnitTestingInt48u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt48uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int48u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int56u
 */
class ReadUnitTestingInt56u : public ReadAttribute {
public:
    ReadUnitTestingInt56u()
        : ReadAttribute("int56u")
    {
    }

    ~ReadUnitTestingInt56u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt56uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int56u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int56u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt56u : public WriteAttribute {
public:
    WriteUnitTestingInt56u()
        : WriteAttribute("int56u")
    {
        AddArgument("attr-name", "int56u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt56u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt56uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int56u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingInt56u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt56u()
        : SubscribeAttribute("int56u")
    {
    }

    ~SubscribeAttributeUnitTestingInt56u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt56uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int56u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int64u
 */
class ReadUnitTestingInt64u : public ReadAttribute {
public:
    ReadUnitTestingInt64u()
        : ReadAttribute("int64u")
    {
    }

    ~ReadUnitTestingInt64u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt64uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int64u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int64u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt64u : public WriteAttribute {
public:
    WriteUnitTestingInt64u()
        : WriteAttribute("int64u")
    {
        AddArgument("attr-name", "int64u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt64u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt64uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int64u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingInt64u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt64u()
        : SubscribeAttribute("int64u")
    {
    }

    ~SubscribeAttributeUnitTestingInt64u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt64uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int64u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int8s
 */
class ReadUnitTestingInt8s : public ReadAttribute {
public:
    ReadUnitTestingInt8s()
        : ReadAttribute("int8s")
    {
    }

    ~ReadUnitTestingInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt8sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int8s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt8s : public WriteAttribute {
public:
    WriteUnitTestingInt8s()
        : WriteAttribute("int8s")
    {
        AddArgument("attr-name", "int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeInt8sWithValue:value
                                       params:params
                                   completion:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("UnitTesting Int8s write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeUnitTestingInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt8s()
        : SubscribeAttribute("int8s")
    {
    }

    ~SubscribeAttributeUnitTestingInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt8sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int16s
 */
class ReadUnitTestingInt16s : public ReadAttribute {
public:
    ReadUnitTestingInt16s()
        : ReadAttribute("int16s")
    {
    }

    ~ReadUnitTestingInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt16sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int16s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt16s : public WriteAttribute {
public:
    WriteUnitTestingInt16s()
        : WriteAttribute("int16s")
    {
        AddArgument("attr-name", "int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeInt16sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int16s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeUnitTestingInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt16s()
        : SubscribeAttribute("int16s")
    {
    }

    ~SubscribeAttributeUnitTestingInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt16sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int24s
 */
class ReadUnitTestingInt24s : public ReadAttribute {
public:
    ReadUnitTestingInt24s()
        : ReadAttribute("int24s")
    {
    }

    ~ReadUnitTestingInt24s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt24sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int24s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int24s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt24s : public WriteAttribute {
public:
    WriteUnitTestingInt24s()
        : WriteAttribute("int24s")
    {
        AddArgument("attr-name", "int24s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt24s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeInt24sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int24s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeUnitTestingInt24s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt24s()
        : SubscribeAttribute("int24s")
    {
    }

    ~SubscribeAttributeUnitTestingInt24s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt24sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int24s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int32s
 */
class ReadUnitTestingInt32s : public ReadAttribute {
public:
    ReadUnitTestingInt32s()
        : ReadAttribute("int32s")
    {
    }

    ~ReadUnitTestingInt32s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt32sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int32s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int32s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt32s : public WriteAttribute {
public:
    WriteUnitTestingInt32s()
        : WriteAttribute("int32s")
    {
        AddArgument("attr-name", "int32s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt32s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeInt32sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int32s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeUnitTestingInt32s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt32s()
        : SubscribeAttribute("int32s")
    {
    }

    ~SubscribeAttributeUnitTestingInt32s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt32sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int32s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int40s
 */
class ReadUnitTestingInt40s : public ReadAttribute {
public:
    ReadUnitTestingInt40s()
        : ReadAttribute("int40s")
    {
    }

    ~ReadUnitTestingInt40s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt40sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int40s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int40s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt40s : public WriteAttribute {
public:
    WriteUnitTestingInt40s()
        : WriteAttribute("int40s")
    {
        AddArgument("attr-name", "int40s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt40s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt40sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int40s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeUnitTestingInt40s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt40s()
        : SubscribeAttribute("int40s")
    {
    }

    ~SubscribeAttributeUnitTestingInt40s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt40sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int40s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int48s
 */
class ReadUnitTestingInt48s : public ReadAttribute {
public:
    ReadUnitTestingInt48s()
        : ReadAttribute("int48s")
    {
    }

    ~ReadUnitTestingInt48s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt48sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int48s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int48s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt48s : public WriteAttribute {
public:
    WriteUnitTestingInt48s()
        : WriteAttribute("int48s")
    {
        AddArgument("attr-name", "int48s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt48s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt48sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int48s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeUnitTestingInt48s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt48s()
        : SubscribeAttribute("int48s")
    {
    }

    ~SubscribeAttributeUnitTestingInt48s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt48sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int48s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int56s
 */
class ReadUnitTestingInt56s : public ReadAttribute {
public:
    ReadUnitTestingInt56s()
        : ReadAttribute("int56s")
    {
    }

    ~ReadUnitTestingInt56s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt56sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int56s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int56s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt56s : public WriteAttribute {
public:
    WriteUnitTestingInt56s()
        : WriteAttribute("int56s")
    {
        AddArgument("attr-name", "int56s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt56s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt56sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int56s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeUnitTestingInt56s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt56s()
        : SubscribeAttribute("int56s")
    {
    }

    ~SubscribeAttributeUnitTestingInt56s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt56sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int56s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int64s
 */
class ReadUnitTestingInt64s : public ReadAttribute {
public:
    ReadUnitTestingInt64s()
        : ReadAttribute("int64s")
    {
    }

    ~ReadUnitTestingInt64s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeInt64sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Int64s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Int64s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingInt64s : public WriteAttribute {
public:
    WriteUnitTestingInt64s()
        : WriteAttribute("int64s")
    {
        AddArgument("attr-name", "int64s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingInt64s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt64sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Int64s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeUnitTestingInt64s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingInt64s()
        : SubscribeAttribute("int64s")
    {
    }

    ~SubscribeAttributeUnitTestingInt64s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeInt64sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Int64s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Enum8
 */
class ReadUnitTestingEnum8 : public ReadAttribute {
public:
    ReadUnitTestingEnum8()
        : ReadAttribute("enum8")
    {
    }

    ~ReadUnitTestingEnum8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeEnum8WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Enum8 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Enum8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingEnum8 : public WriteAttribute {
public:
    WriteUnitTestingEnum8()
        : WriteAttribute("enum8")
    {
        AddArgument("attr-name", "enum8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingEnum8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeEnum8WithValue:value
                                       params:params
                                   completion:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("UnitTesting Enum8 write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingEnum8 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingEnum8()
        : SubscribeAttribute("enum8")
    {
    }

    ~SubscribeAttributeUnitTestingEnum8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEnum8WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Enum8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Enum16
 */
class ReadUnitTestingEnum16 : public ReadAttribute {
public:
    ReadUnitTestingEnum16()
        : ReadAttribute("enum16")
    {
    }

    ~ReadUnitTestingEnum16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeEnum16WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Enum16 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Enum16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingEnum16 : public WriteAttribute {
public:
    WriteUnitTestingEnum16()
        : WriteAttribute("enum16")
    {
        AddArgument("attr-name", "enum16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingEnum16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeEnum16WithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting Enum16 write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeUnitTestingEnum16 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingEnum16()
        : SubscribeAttribute("enum16")
    {
    }

    ~SubscribeAttributeUnitTestingEnum16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEnum16WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Enum16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FloatSingle
 */
class ReadUnitTestingFloatSingle : public ReadAttribute {
public:
    ReadUnitTestingFloatSingle()
        : ReadAttribute("float-single")
    {
    }

    ~ReadUnitTestingFloatSingle() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeFloatSingleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.FloatSingle response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting FloatSingle read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingFloatSingle : public WriteAttribute {
public:
    WriteUnitTestingFloatSingle()
        : WriteAttribute("float-single")
    {
        AddArgument("attr-name", "float-single");
        AddArgument("attr-value", -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingFloatSingle() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithFloat:mValue];

        [cluster writeAttributeFloatSingleWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("UnitTesting FloatSingle write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    float mValue;
};

class SubscribeAttributeUnitTestingFloatSingle : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingFloatSingle()
        : SubscribeAttribute("float-single")
    {
    }

    ~SubscribeAttributeUnitTestingFloatSingle() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeFloatSingleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.FloatSingle response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FloatDouble
 */
class ReadUnitTestingFloatDouble : public ReadAttribute {
public:
    ReadUnitTestingFloatDouble()
        : ReadAttribute("float-double")
    {
    }

    ~ReadUnitTestingFloatDouble() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeFloatDoubleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.FloatDouble response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting FloatDouble read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingFloatDouble : public WriteAttribute {
public:
    WriteUnitTestingFloatDouble()
        : WriteAttribute("float-double")
    {
        AddArgument("attr-name", "float-double");
        AddArgument("attr-value", -std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity(), &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingFloatDouble() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithDouble:mValue];

        [cluster writeAttributeFloatDoubleWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("UnitTesting FloatDouble write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    double mValue;
};

class SubscribeAttributeUnitTestingFloatDouble : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingFloatDouble()
        : SubscribeAttribute("float-double")
    {
    }

    ~SubscribeAttributeUnitTestingFloatDouble() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeFloatDoubleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.FloatDouble response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OctetString
 */
class ReadUnitTestingOctetString : public ReadAttribute {
public:
    ReadUnitTestingOctetString()
        : ReadAttribute("octet-string")
    {
    }

    ~ReadUnitTestingOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeOctetStringWithCompletion:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.OctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting OctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingOctetString : public WriteAttribute {
public:
    WriteUnitTestingOctetString()
        : WriteAttribute("octet-string")
    {
        AddArgument("attr-name", "octet-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSData * _Nonnull value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()];

        [cluster writeAttributeOctetStringWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("UnitTesting OctetString write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeUnitTestingOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingOctetString()
        : SubscribeAttribute("octet-string")
    {
    }

    ~SubscribeAttributeUnitTestingOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.OctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListInt8u
 */
class ReadUnitTestingListInt8u : public ReadAttribute {
public:
    ReadUnitTestingListInt8u()
        : ReadAttribute("list-int8u")
    {
    }

    ~ReadUnitTestingListInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeListInt8uWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.ListInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting ListInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingListInt8u : public WriteAttribute {
public:
    WriteUnitTestingListInt8u()
        : WriteAttribute("list-int8u")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-int8u");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingListInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedChar:entry_0];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListInt8uWithValue:value
                                           params:params
                                       completion:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("UnitTesting 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 SubscribeAttributeUnitTestingListInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingListInt8u()
        : SubscribeAttribute("list-int8u")
    {
    }

    ~SubscribeAttributeUnitTestingListInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeListInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.ListInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListOctetString
 */
class ReadUnitTestingListOctetString : public ReadAttribute {
public:
    ReadUnitTestingListOctetString()
        : ReadAttribute("list-octet-string")
    {
    }

    ~ReadUnitTestingListOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeListOctetStringWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.ListOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting ListOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingListOctetString : public WriteAttribute {
public:
    WriteUnitTestingListOctetString()
        : WriteAttribute("list-octet-string")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-octet-string");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingListOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                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("UnitTesting 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 SubscribeAttributeUnitTestingListOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingListOctetString()
        : SubscribeAttribute("list-octet-string")
    {
    }

    ~SubscribeAttributeUnitTestingListOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeListOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.ListOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListStructOctetString
 */
class ReadUnitTestingListStructOctetString : public ReadAttribute {
public:
    ReadUnitTestingListStructOctetString()
        : ReadAttribute("list-struct-octet-string")
    {
    }

    ~ReadUnitTestingListStructOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeListStructOctetStringWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.ListStructOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting ListStructOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingListStructOctetString : public WriteAttribute {
public:
    WriteUnitTestingListStructOctetString()
        : WriteAttribute("list-struct-octet-string")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-struct-octet-string");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingListStructOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRUnitTestingClusterTestListStructOctet * newElement_0;
                newElement_0 = [MTRUnitTestingClusterTestListStructOctet 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("UnitTesting ListStructOctetString write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::Structs::TestListStructOctet::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::Structs::TestListStructOctet::Type>>
        mComplex;
};

class SubscribeAttributeUnitTestingListStructOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingListStructOctetString()
        : SubscribeAttribute("list-struct-octet-string")
    {
    }

    ~SubscribeAttributeUnitTestingListStructOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeListStructOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.ListStructOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LongOctetString
 */
class ReadUnitTestingLongOctetString : public ReadAttribute {
public:
    ReadUnitTestingLongOctetString()
        : ReadAttribute("long-octet-string")
    {
    }

    ~ReadUnitTestingLongOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeLongOctetStringWithCompletion:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.LongOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting LongOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingLongOctetString : public WriteAttribute {
public:
    WriteUnitTestingLongOctetString()
        : WriteAttribute("long-octet-string")
    {
        AddArgument("attr-name", "long-octet-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingLongOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSData * _Nonnull value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()];

        [cluster writeAttributeLongOctetStringWithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("UnitTesting LongOctetString write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeUnitTestingLongOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingLongOctetString()
        : SubscribeAttribute("long-octet-string")
    {
    }

    ~SubscribeAttributeUnitTestingLongOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeLongOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.LongOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CharString
 */
class ReadUnitTestingCharString : public ReadAttribute {
public:
    ReadUnitTestingCharString()
        : ReadAttribute("char-string")
    {
    }

    ~ReadUnitTestingCharString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeCharStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.CharString response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting CharString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingCharString : public WriteAttribute {
public:
    WriteUnitTestingCharString()
        : WriteAttribute("char-string")
    {
        AddArgument("attr-name", "char-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingCharString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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("UnitTesting CharString write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeUnitTestingCharString : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingCharString()
        : SubscribeAttribute("char-string")
    {
    }

    ~SubscribeAttributeUnitTestingCharString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeCharStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.CharString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LongCharString
 */
class ReadUnitTestingLongCharString : public ReadAttribute {
public:
    ReadUnitTestingLongCharString()
        : ReadAttribute("long-char-string")
    {
    }

    ~ReadUnitTestingLongCharString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeLongCharStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.LongCharString response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting LongCharString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingLongCharString : public WriteAttribute {
public:
    WriteUnitTestingLongCharString()
        : WriteAttribute("long-char-string")
    {
        AddArgument("attr-name", "long-char-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingLongCharString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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("UnitTesting LongCharString write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeUnitTestingLongCharString : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingLongCharString()
        : SubscribeAttribute("long-char-string")
    {
    }

    ~SubscribeAttributeUnitTestingLongCharString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeLongCharStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.LongCharString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EpochUs
 */
class ReadUnitTestingEpochUs : public ReadAttribute {
public:
    ReadUnitTestingEpochUs()
        : ReadAttribute("epoch-us")
    {
    }

    ~ReadUnitTestingEpochUs() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeEpochUsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.EpochUs response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting EpochUs read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingEpochUs : public WriteAttribute {
public:
    WriteUnitTestingEpochUs()
        : WriteAttribute("epoch-us")
    {
        AddArgument("attr-name", "epoch-us");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingEpochUs() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeEpochUsWithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("UnitTesting EpochUs write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingEpochUs : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingEpochUs()
        : SubscribeAttribute("epoch-us")
    {
    }

    ~SubscribeAttributeUnitTestingEpochUs() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEpochUsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.EpochUs response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EpochS
 */
class ReadUnitTestingEpochS : public ReadAttribute {
public:
    ReadUnitTestingEpochS()
        : ReadAttribute("epoch-s")
    {
    }

    ~ReadUnitTestingEpochS() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeEpochSWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.EpochS response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting EpochS read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingEpochS : public WriteAttribute {
public:
    WriteUnitTestingEpochS()
        : WriteAttribute("epoch-s")
    {
        AddArgument("attr-name", "epoch-s");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingEpochS() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeEpochSWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("UnitTesting EpochS write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeUnitTestingEpochS : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingEpochS()
        : SubscribeAttribute("epoch-s")
    {
    }

    ~SubscribeAttributeUnitTestingEpochS() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEpochSWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.EpochS response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorId
 */
class ReadUnitTestingVendorId : public ReadAttribute {
public:
    ReadUnitTestingVendorId()
        : ReadAttribute("vendor-id")
    {
    }

    ~ReadUnitTestingVendorId() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeVendorIdWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.VendorId response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting VendorId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingVendorId : public WriteAttribute {
public:
    WriteUnitTestingVendorId()
        : WriteAttribute("vendor-id")
    {
        AddArgument("attr-name", "vendor-id");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingVendorId() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeVendorIdWithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("UnitTesting VendorId write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    chip::VendorId mValue;
};

class SubscribeAttributeUnitTestingVendorId : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingVendorId()
        : SubscribeAttribute("vendor-id")
    {
    }

    ~SubscribeAttributeUnitTestingVendorId() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeVendorIdWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.VendorId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListNullablesAndOptionalsStruct
 */
class ReadUnitTestingListNullablesAndOptionalsStruct : public ReadAttribute {
public:
    ReadUnitTestingListNullablesAndOptionalsStruct()
        : ReadAttribute("list-nullables-and-optionals-struct")
    {
    }

    ~ReadUnitTestingListNullablesAndOptionalsStruct() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster
            readAttributeListNullablesAndOptionalsStructWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.ListNullablesAndOptionalsStruct response %@", [value description]);
                if (error != nil) {
                    LogNSError("UnitTesting ListNullablesAndOptionalsStruct read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingListNullablesAndOptionalsStruct : public WriteAttribute {
public:
    WriteUnitTestingListNullablesAndOptionalsStruct()
        : WriteAttribute("list-nullables-and-optionals-struct")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-nullables-and-optionals-struct");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingListNullablesAndOptionalsStruct() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRUnitTestingClusterNullablesAndOptionalsStruct * newElement_0;
                newElement_0 = [MTRUnitTestingClusterNullablesAndOptionalsStruct 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 = [MTRUnitTestingClusterSimpleStruct 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 = [MTRUnitTestingClusterSimpleStruct 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 = [MTRUnitTestingClusterSimpleStruct 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(
                                                                         "UnitTesting ListNullablesAndOptionalsStruct write Error",
                                                                         error);
                                                                 }
                                                                 SetCommandExitStatus(error);
                                                             }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::Structs::NullablesAndOptionalsStruct::Type> mValue;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::Structs::NullablesAndOptionalsStruct::Type>>
        mComplex;
};

class SubscribeAttributeUnitTestingListNullablesAndOptionalsStruct : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingListNullablesAndOptionalsStruct()
        : SubscribeAttribute("list-nullables-and-optionals-struct")
    {
    }

    ~SubscribeAttributeUnitTestingListNullablesAndOptionalsStruct() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeListNullablesAndOptionalsStructWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.ListNullablesAndOptionalsStruct response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnumAttr
 */
class ReadUnitTestingEnumAttr : public ReadAttribute {
public:
    ReadUnitTestingEnumAttr()
        : ReadAttribute("enum-attr")
    {
    }

    ~ReadUnitTestingEnumAttr() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeEnumAttrWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.EnumAttr response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting EnumAttr read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingEnumAttr : public WriteAttribute {
public:
    WriteUnitTestingEnumAttr()
        : WriteAttribute("enum-attr")
    {
        AddArgument("attr-name", "enum-attr");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingEnumAttr() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeEnumAttrWithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("UnitTesting EnumAttr write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingEnumAttr : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingEnumAttr()
        : SubscribeAttribute("enum-attr")
    {
    }

    ~SubscribeAttributeUnitTestingEnumAttr() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEnumAttrWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.EnumAttr response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StructAttr
 */
class ReadUnitTestingStructAttr : public ReadAttribute {
public:
    ReadUnitTestingStructAttr()
        : ReadAttribute("struct-attr")
    {
    }

    ~ReadUnitTestingStructAttr() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeStructAttrWithCompletion:^(
            MTRUnitTestingClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.StructAttr response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting StructAttr read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingStructAttr : public WriteAttribute {
public:
    WriteUnitTestingStructAttr()
        : WriteAttribute("struct-attr")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "struct-attr");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingStructAttr() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        MTRUnitTestingClusterSimpleStruct * _Nonnull value;
        value = [MTRUnitTestingClusterSimpleStruct 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("UnitTesting StructAttr write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type mValue;
    TypedComplexArgument<chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type> mComplex;
};

class SubscribeAttributeUnitTestingStructAttr : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingStructAttr()
        : SubscribeAttribute("struct-attr")
    {
    }

    ~SubscribeAttributeUnitTestingStructAttr() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeStructAttrWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRUnitTestingClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.StructAttr response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt8u
 */
class ReadUnitTestingRangeRestrictedInt8u : public ReadAttribute {
public:
    ReadUnitTestingRangeRestrictedInt8u()
        : ReadAttribute("range-restricted-int8u")
    {
    }

    ~ReadUnitTestingRangeRestrictedInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.RangeRestrictedInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting RangeRestrictedInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingRangeRestrictedInt8u : public WriteAttribute {
public:
    WriteUnitTestingRangeRestrictedInt8u()
        : WriteAttribute("range-restricted-int8u")
    {
        AddArgument("attr-name", "range-restricted-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingRangeRestrictedInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeRangeRestrictedInt8uWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("UnitTesting RangeRestrictedInt8u write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingRangeRestrictedInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingRangeRestrictedInt8u()
        : SubscribeAttribute("range-restricted-int8u")
    {
    }

    ~SubscribeAttributeUnitTestingRangeRestrictedInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeRangeRestrictedInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.RangeRestrictedInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt8s
 */
class ReadUnitTestingRangeRestrictedInt8s : public ReadAttribute {
public:
    ReadUnitTestingRangeRestrictedInt8s()
        : ReadAttribute("range-restricted-int8s")
    {
    }

    ~ReadUnitTestingRangeRestrictedInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt8sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.RangeRestrictedInt8s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting RangeRestrictedInt8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingRangeRestrictedInt8s : public WriteAttribute {
public:
    WriteUnitTestingRangeRestrictedInt8s()
        : WriteAttribute("range-restricted-int8s")
    {
        AddArgument("attr-name", "range-restricted-int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingRangeRestrictedInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeRangeRestrictedInt8sWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("UnitTesting RangeRestrictedInt8s write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeUnitTestingRangeRestrictedInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingRangeRestrictedInt8s()
        : SubscribeAttribute("range-restricted-int8s")
    {
    }

    ~SubscribeAttributeUnitTestingRangeRestrictedInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeRangeRestrictedInt8sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.RangeRestrictedInt8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt16u
 */
class ReadUnitTestingRangeRestrictedInt16u : public ReadAttribute {
public:
    ReadUnitTestingRangeRestrictedInt16u()
        : ReadAttribute("range-restricted-int16u")
    {
    }

    ~ReadUnitTestingRangeRestrictedInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt16uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.RangeRestrictedInt16u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting RangeRestrictedInt16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingRangeRestrictedInt16u : public WriteAttribute {
public:
    WriteUnitTestingRangeRestrictedInt16u()
        : WriteAttribute("range-restricted-int16u")
    {
        AddArgument("attr-name", "range-restricted-int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingRangeRestrictedInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeRangeRestrictedInt16uWithValue:value
                                                       params:params
                                                   completion:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError("UnitTesting RangeRestrictedInt16u write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeUnitTestingRangeRestrictedInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingRangeRestrictedInt16u()
        : SubscribeAttribute("range-restricted-int16u")
    {
    }

    ~SubscribeAttributeUnitTestingRangeRestrictedInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeRangeRestrictedInt16uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.RangeRestrictedInt16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt16s
 */
class ReadUnitTestingRangeRestrictedInt16s : public ReadAttribute {
public:
    ReadUnitTestingRangeRestrictedInt16s()
        : ReadAttribute("range-restricted-int16s")
    {
    }

    ~ReadUnitTestingRangeRestrictedInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt16sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.RangeRestrictedInt16s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting RangeRestrictedInt16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingRangeRestrictedInt16s : public WriteAttribute {
public:
    WriteUnitTestingRangeRestrictedInt16s()
        : WriteAttribute("range-restricted-int16s")
    {
        AddArgument("attr-name", "range-restricted-int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingRangeRestrictedInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeRangeRestrictedInt16sWithValue:value
                                                       params:params
                                                   completion:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError("UnitTesting RangeRestrictedInt16s write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeUnitTestingRangeRestrictedInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingRangeRestrictedInt16s()
        : SubscribeAttribute("range-restricted-int16s")
    {
    }

    ~SubscribeAttributeUnitTestingRangeRestrictedInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeRangeRestrictedInt16sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.RangeRestrictedInt16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListLongOctetString
 */
class ReadUnitTestingListLongOctetString : public ReadAttribute {
public:
    ReadUnitTestingListLongOctetString()
        : ReadAttribute("list-long-octet-string")
    {
    }

    ~ReadUnitTestingListLongOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeListLongOctetStringWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.ListLongOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting ListLongOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingListLongOctetString : public WriteAttribute {
public:
    WriteUnitTestingListLongOctetString()
        : WriteAttribute("list-long-octet-string")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-long-octet-string");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingListLongOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                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("UnitTesting 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 SubscribeAttributeUnitTestingListLongOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingListLongOctetString()
        : SubscribeAttribute("list-long-octet-string")
    {
    }

    ~SubscribeAttributeUnitTestingListLongOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeListLongOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.ListLongOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListFabricScoped
 */
class ReadUnitTestingListFabricScoped : public ReadAttribute {
public:
    ReadUnitTestingListFabricScoped()
        : ReadAttribute("list-fabric-scoped")
    {
    }

    ~ReadUnitTestingListFabricScoped() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster readAttributeListFabricScopedWithParams:params
                                              completion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                                  NSLog(@"UnitTesting.ListFabricScoped response %@", [value description]);
                                                  if (error != nil) {
                                                      LogNSError("UnitTesting ListFabricScoped read Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingListFabricScoped : public WriteAttribute {
public:
    WriteUnitTestingListFabricScoped()
        : WriteAttribute("list-fabric-scoped")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-fabric-scoped");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingListFabricScoped() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRUnitTestingClusterTestFabricScoped * newElement_0;
                newElement_0 = [MTRUnitTestingClusterTestFabricScoped 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 = [MTRUnitTestingClusterSimpleStruct 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("UnitTesting ListFabricScoped write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::Structs::TestFabricScoped::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::UnitTesting::Structs::TestFabricScoped::Type>>
        mComplex;
};

class SubscribeAttributeUnitTestingListFabricScoped : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingListFabricScoped()
        : SubscribeAttribute("list-fabric-scoped")
    {
    }

    ~SubscribeAttributeUnitTestingListFabricScoped() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeListFabricScopedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.ListFabricScoped response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TimedWriteBoolean
 */
class ReadUnitTestingTimedWriteBoolean : public ReadAttribute {
public:
    ReadUnitTestingTimedWriteBoolean()
        : ReadAttribute("timed-write-boolean")
    {
    }

    ~ReadUnitTestingTimedWriteBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeTimedWriteBooleanWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.TimedWriteBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting TimedWriteBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingTimedWriteBoolean : public WriteAttribute {
public:
    WriteUnitTestingTimedWriteBoolean()
        : WriteAttribute("timed-write-boolean")
    {
        AddArgument("attr-name", "timed-write-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingTimedWriteBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeTimedWriteBooleanWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("UnitTesting TimedWriteBoolean write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeUnitTestingTimedWriteBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingTimedWriteBoolean()
        : SubscribeAttribute("timed-write-boolean")
    {
    }

    ~SubscribeAttributeUnitTestingTimedWriteBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeTimedWriteBooleanWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.TimedWriteBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneralErrorBoolean
 */
class ReadUnitTestingGeneralErrorBoolean : public ReadAttribute {
public:
    ReadUnitTestingGeneralErrorBoolean()
        : ReadAttribute("general-error-boolean")
    {
    }

    ~ReadUnitTestingGeneralErrorBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeGeneralErrorBooleanWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.GeneralErrorBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting GeneralErrorBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingGeneralErrorBoolean : public WriteAttribute {
public:
    WriteUnitTestingGeneralErrorBoolean()
        : WriteAttribute("general-error-boolean")
    {
        AddArgument("attr-name", "general-error-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingGeneralErrorBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeGeneralErrorBooleanWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("UnitTesting GeneralErrorBoolean write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeUnitTestingGeneralErrorBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingGeneralErrorBoolean()
        : SubscribeAttribute("general-error-boolean")
    {
    }

    ~SubscribeAttributeUnitTestingGeneralErrorBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeGeneralErrorBooleanWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.GeneralErrorBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterErrorBoolean
 */
class ReadUnitTestingClusterErrorBoolean : public ReadAttribute {
public:
    ReadUnitTestingClusterErrorBoolean()
        : ReadAttribute("cluster-error-boolean")
    {
    }

    ~ReadUnitTestingClusterErrorBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeClusterErrorBooleanWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.ClusterErrorBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting ClusterErrorBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingClusterErrorBoolean : public WriteAttribute {
public:
    WriteUnitTestingClusterErrorBoolean()
        : WriteAttribute("cluster-error-boolean")
    {
        AddArgument("attr-name", "cluster-error-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingClusterErrorBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeClusterErrorBooleanWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("UnitTesting ClusterErrorBoolean write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeUnitTestingClusterErrorBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingClusterErrorBoolean()
        : SubscribeAttribute("cluster-error-boolean")
    {
    }

    ~SubscribeAttributeUnitTestingClusterErrorBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeClusterErrorBooleanWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.ClusterErrorBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Unsupported
 */
class ReadUnitTestingUnsupported : public ReadAttribute {
public:
    ReadUnitTestingUnsupported()
        : ReadAttribute("unsupported")
    {
    }

    ~ReadUnitTestingUnsupported() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeUnsupportedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.Unsupported response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting Unsupported read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingUnsupported : public WriteAttribute {
public:
    WriteUnitTestingUnsupported()
        : WriteAttribute("unsupported")
    {
        AddArgument("attr-name", "unsupported");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingUnsupported() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeUnsupportedWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("UnitTesting Unsupported write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeUnitTestingUnsupported : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingUnsupported()
        : SubscribeAttribute("unsupported")
    {
    }

    ~SubscribeAttributeUnitTestingUnsupported() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeUnsupportedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.Unsupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBoolean
 */
class ReadUnitTestingNullableBoolean : public ReadAttribute {
public:
    ReadUnitTestingNullableBoolean()
        : ReadAttribute("nullable-boolean")
    {
    }

    ~ReadUnitTestingNullableBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableBooleanWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableBoolean : public WriteAttribute {
public:
    WriteUnitTestingNullableBoolean()
        : WriteAttribute("nullable-boolean")
    {
        AddArgument("attr-name", "nullable-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeNullableBooleanWithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("UnitTesting NullableBoolean write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeUnitTestingNullableBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableBoolean()
        : SubscribeAttribute("nullable-boolean")
    {
    }

    ~SubscribeAttributeUnitTestingNullableBoolean() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableBooleanWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap8
 */
class ReadUnitTestingNullableBitmap8 : public ReadAttribute {
public:
    ReadUnitTestingNullableBitmap8()
        : ReadAttribute("nullable-bitmap8")
    {
    }

    ~ReadUnitTestingNullableBitmap8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableBitmap8WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableBitmap8 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableBitmap8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableBitmap8 : public WriteAttribute {
public:
    WriteUnitTestingNullableBitmap8()
        : WriteAttribute("nullable-bitmap8")
    {
        AddArgument("attr-name", "nullable-bitmap8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableBitmap8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableBitmap8WithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("UnitTesting NullableBitmap8 write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingNullableBitmap8 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableBitmap8()
        : SubscribeAttribute("nullable-bitmap8")
    {
    }

    ~SubscribeAttributeUnitTestingNullableBitmap8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableBitmap8WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableBitmap8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap16
 */
class ReadUnitTestingNullableBitmap16 : public ReadAttribute {
public:
    ReadUnitTestingNullableBitmap16()
        : ReadAttribute("nullable-bitmap16")
    {
    }

    ~ReadUnitTestingNullableBitmap16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableBitmap16WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableBitmap16 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableBitmap16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableBitmap16 : public WriteAttribute {
public:
    WriteUnitTestingNullableBitmap16()
        : WriteAttribute("nullable-bitmap16")
    {
        AddArgument("attr-name", "nullable-bitmap16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableBitmap16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeNullableBitmap16WithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("UnitTesting NullableBitmap16 write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeUnitTestingNullableBitmap16 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableBitmap16()
        : SubscribeAttribute("nullable-bitmap16")
    {
    }

    ~SubscribeAttributeUnitTestingNullableBitmap16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableBitmap16WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableBitmap16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap32
 */
class ReadUnitTestingNullableBitmap32 : public ReadAttribute {
public:
    ReadUnitTestingNullableBitmap32()
        : ReadAttribute("nullable-bitmap32")
    {
    }

    ~ReadUnitTestingNullableBitmap32() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableBitmap32WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableBitmap32 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableBitmap32 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableBitmap32 : public WriteAttribute {
public:
    WriteUnitTestingNullableBitmap32()
        : WriteAttribute("nullable-bitmap32")
    {
        AddArgument("attr-name", "nullable-bitmap32");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableBitmap32() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeNullableBitmap32WithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("UnitTesting NullableBitmap32 write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeUnitTestingNullableBitmap32 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableBitmap32()
        : SubscribeAttribute("nullable-bitmap32")
    {
    }

    ~SubscribeAttributeUnitTestingNullableBitmap32() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableBitmap32WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableBitmap32 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap64
 */
class ReadUnitTestingNullableBitmap64 : public ReadAttribute {
public:
    ReadUnitTestingNullableBitmap64()
        : ReadAttribute("nullable-bitmap64")
    {
    }

    ~ReadUnitTestingNullableBitmap64() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableBitmap64WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableBitmap64 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableBitmap64 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableBitmap64 : public WriteAttribute {
public:
    WriteUnitTestingNullableBitmap64()
        : WriteAttribute("nullable-bitmap64")
    {
        AddArgument("attr-name", "nullable-bitmap64");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableBitmap64() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableBitmap64WithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("UnitTesting NullableBitmap64 write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingNullableBitmap64 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableBitmap64()
        : SubscribeAttribute("nullable-bitmap64")
    {
    }

    ~SubscribeAttributeUnitTestingNullableBitmap64() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableBitmap64WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableBitmap64 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt8u
 */
class ReadUnitTestingNullableInt8u : public ReadAttribute {
public:
    ReadUnitTestingNullableInt8u()
        : ReadAttribute("nullable-int8u")
    {
    }

    ~ReadUnitTestingNullableInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt8u : public WriteAttribute {
public:
    WriteUnitTestingNullableInt8u()
        : WriteAttribute("nullable-int8u")
    {
        AddArgument("attr-name", "nullable-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableInt8uWithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("UnitTesting NullableInt8u write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt8u()
        : SubscribeAttribute("nullable-int8u")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt16u
 */
class ReadUnitTestingNullableInt16u : public ReadAttribute {
public:
    ReadUnitTestingNullableInt16u()
        : ReadAttribute("nullable-int16u")
    {
    }

    ~ReadUnitTestingNullableInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt16uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt16u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt16u : public WriteAttribute {
public:
    WriteUnitTestingNullableInt16u()
        : WriteAttribute("nullable-int16u")
    {
        AddArgument("attr-name", "nullable-int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeNullableInt16uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt16u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt16u()
        : SubscribeAttribute("nullable-int16u")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt16uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt24u
 */
class ReadUnitTestingNullableInt24u : public ReadAttribute {
public:
    ReadUnitTestingNullableInt24u()
        : ReadAttribute("nullable-int24u")
    {
    }

    ~ReadUnitTestingNullableInt24u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt24uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt24u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt24u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt24u : public WriteAttribute {
public:
    WriteUnitTestingNullableInt24u()
        : WriteAttribute("nullable-int24u")
    {
        AddArgument("attr-name", "nullable-int24u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt24u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeNullableInt24uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt24u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt24u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt24u()
        : SubscribeAttribute("nullable-int24u")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt24u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt24uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt24u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt32u
 */
class ReadUnitTestingNullableInt32u : public ReadAttribute {
public:
    ReadUnitTestingNullableInt32u()
        : ReadAttribute("nullable-int32u")
    {
    }

    ~ReadUnitTestingNullableInt32u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt32uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt32u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt32u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt32u : public WriteAttribute {
public:
    WriteUnitTestingNullableInt32u()
        : WriteAttribute("nullable-int32u")
    {
        AddArgument("attr-name", "nullable-int32u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt32u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeNullableInt32uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt32u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt32u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt32u()
        : SubscribeAttribute("nullable-int32u")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt32u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt32uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt32u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt40u
 */
class ReadUnitTestingNullableInt40u : public ReadAttribute {
public:
    ReadUnitTestingNullableInt40u()
        : ReadAttribute("nullable-int40u")
    {
    }

    ~ReadUnitTestingNullableInt40u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt40uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt40u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt40u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt40u : public WriteAttribute {
public:
    WriteUnitTestingNullableInt40u()
        : WriteAttribute("nullable-int40u")
    {
        AddArgument("attr-name", "nullable-int40u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt40u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt40uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt40u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt40u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt40u()
        : SubscribeAttribute("nullable-int40u")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt40u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt40uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt40u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt48u
 */
class ReadUnitTestingNullableInt48u : public ReadAttribute {
public:
    ReadUnitTestingNullableInt48u()
        : ReadAttribute("nullable-int48u")
    {
    }

    ~ReadUnitTestingNullableInt48u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt48uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt48u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt48u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt48u : public WriteAttribute {
public:
    WriteUnitTestingNullableInt48u()
        : WriteAttribute("nullable-int48u")
    {
        AddArgument("attr-name", "nullable-int48u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt48u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt48uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt48u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt48u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt48u()
        : SubscribeAttribute("nullable-int48u")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt48u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt48uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt48u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt56u
 */
class ReadUnitTestingNullableInt56u : public ReadAttribute {
public:
    ReadUnitTestingNullableInt56u()
        : ReadAttribute("nullable-int56u")
    {
    }

    ~ReadUnitTestingNullableInt56u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt56uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt56u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt56u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt56u : public WriteAttribute {
public:
    WriteUnitTestingNullableInt56u()
        : WriteAttribute("nullable-int56u")
    {
        AddArgument("attr-name", "nullable-int56u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt56u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt56uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt56u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt56u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt56u()
        : SubscribeAttribute("nullable-int56u")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt56u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt56uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt56u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt64u
 */
class ReadUnitTestingNullableInt64u : public ReadAttribute {
public:
    ReadUnitTestingNullableInt64u()
        : ReadAttribute("nullable-int64u")
    {
    }

    ~ReadUnitTestingNullableInt64u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt64uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt64u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt64u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt64u : public WriteAttribute {
public:
    WriteUnitTestingNullableInt64u()
        : WriteAttribute("nullable-int64u")
    {
        AddArgument("attr-name", "nullable-int64u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt64u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt64uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt64u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt64u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt64u()
        : SubscribeAttribute("nullable-int64u")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt64u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt64uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt64u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt8s
 */
class ReadUnitTestingNullableInt8s : public ReadAttribute {
public:
    ReadUnitTestingNullableInt8s()
        : ReadAttribute("nullable-int8s")
    {
    }

    ~ReadUnitTestingNullableInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt8sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt8s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt8s : public WriteAttribute {
public:
    WriteUnitTestingNullableInt8s()
        : WriteAttribute("nullable-int8s")
    {
        AddArgument("attr-name", "nullable-int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeNullableInt8sWithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("UnitTesting NullableInt8s write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt8s()
        : SubscribeAttribute("nullable-int8s")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt8sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt16s
 */
class ReadUnitTestingNullableInt16s : public ReadAttribute {
public:
    ReadUnitTestingNullableInt16s()
        : ReadAttribute("nullable-int16s")
    {
    }

    ~ReadUnitTestingNullableInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt16sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt16s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt16s : public WriteAttribute {
public:
    WriteUnitTestingNullableInt16s()
        : WriteAttribute("nullable-int16s")
    {
        AddArgument("attr-name", "nullable-int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeNullableInt16sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt16s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt16s()
        : SubscribeAttribute("nullable-int16s")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt16sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt24s
 */
class ReadUnitTestingNullableInt24s : public ReadAttribute {
public:
    ReadUnitTestingNullableInt24s()
        : ReadAttribute("nullable-int24s")
    {
    }

    ~ReadUnitTestingNullableInt24s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt24sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt24s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt24s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt24s : public WriteAttribute {
public:
    WriteUnitTestingNullableInt24s()
        : WriteAttribute("nullable-int24s")
    {
        AddArgument("attr-name", "nullable-int24s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt24s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeNullableInt24sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt24s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt24s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt24s()
        : SubscribeAttribute("nullable-int24s")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt24s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt24sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt24s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt32s
 */
class ReadUnitTestingNullableInt32s : public ReadAttribute {
public:
    ReadUnitTestingNullableInt32s()
        : ReadAttribute("nullable-int32s")
    {
    }

    ~ReadUnitTestingNullableInt32s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt32sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt32s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt32s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt32s : public WriteAttribute {
public:
    WriteUnitTestingNullableInt32s()
        : WriteAttribute("nullable-int32s")
    {
        AddArgument("attr-name", "nullable-int32s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt32s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeNullableInt32sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt32s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt32s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt32s()
        : SubscribeAttribute("nullable-int32s")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt32s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt32sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt32s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt40s
 */
class ReadUnitTestingNullableInt40s : public ReadAttribute {
public:
    ReadUnitTestingNullableInt40s()
        : ReadAttribute("nullable-int40s")
    {
    }

    ~ReadUnitTestingNullableInt40s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt40sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt40s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt40s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt40s : public WriteAttribute {
public:
    WriteUnitTestingNullableInt40s()
        : WriteAttribute("nullable-int40s")
    {
        AddArgument("attr-name", "nullable-int40s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt40s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt40sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt40s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt40s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt40s()
        : SubscribeAttribute("nullable-int40s")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt40s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt40sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt40s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt48s
 */
class ReadUnitTestingNullableInt48s : public ReadAttribute {
public:
    ReadUnitTestingNullableInt48s()
        : ReadAttribute("nullable-int48s")
    {
    }

    ~ReadUnitTestingNullableInt48s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt48sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt48s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt48s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt48s : public WriteAttribute {
public:
    WriteUnitTestingNullableInt48s()
        : WriteAttribute("nullable-int48s")
    {
        AddArgument("attr-name", "nullable-int48s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt48s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt48sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt48s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt48s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt48s()
        : SubscribeAttribute("nullable-int48s")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt48s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt48sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt48s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt56s
 */
class ReadUnitTestingNullableInt56s : public ReadAttribute {
public:
    ReadUnitTestingNullableInt56s()
        : ReadAttribute("nullable-int56s")
    {
    }

    ~ReadUnitTestingNullableInt56s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt56sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt56s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt56s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt56s : public WriteAttribute {
public:
    WriteUnitTestingNullableInt56s()
        : WriteAttribute("nullable-int56s")
    {
        AddArgument("attr-name", "nullable-int56s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt56s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt56sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt56s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt56s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt56s()
        : SubscribeAttribute("nullable-int56s")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt56s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt56sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt56s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt64s
 */
class ReadUnitTestingNullableInt64s : public ReadAttribute {
public:
    ReadUnitTestingNullableInt64s()
        : ReadAttribute("nullable-int64s")
    {
    }

    ~ReadUnitTestingNullableInt64s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableInt64sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableInt64s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableInt64s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableInt64s : public WriteAttribute {
public:
    WriteUnitTestingNullableInt64s()
        : WriteAttribute("nullable-int64s")
    {
        AddArgument("attr-name", "nullable-int64s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableInt64s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt64sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableInt64s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeUnitTestingNullableInt64s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableInt64s()
        : SubscribeAttribute("nullable-int64s")
    {
    }

    ~SubscribeAttributeUnitTestingNullableInt64s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableInt64sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableInt64s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableEnum8
 */
class ReadUnitTestingNullableEnum8 : public ReadAttribute {
public:
    ReadUnitTestingNullableEnum8()
        : ReadAttribute("nullable-enum8")
    {
    }

    ~ReadUnitTestingNullableEnum8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableEnum8WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableEnum8 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableEnum8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableEnum8 : public WriteAttribute {
public:
    WriteUnitTestingNullableEnum8()
        : WriteAttribute("nullable-enum8")
    {
        AddArgument("attr-name", "nullable-enum8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableEnum8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableEnum8WithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("UnitTesting NullableEnum8 write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingNullableEnum8 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableEnum8()
        : SubscribeAttribute("nullable-enum8")
    {
    }

    ~SubscribeAttributeUnitTestingNullableEnum8() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableEnum8WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableEnum8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableEnum16
 */
class ReadUnitTestingNullableEnum16 : public ReadAttribute {
public:
    ReadUnitTestingNullableEnum16()
        : ReadAttribute("nullable-enum16")
    {
    }

    ~ReadUnitTestingNullableEnum16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableEnum16WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableEnum16 response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableEnum16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableEnum16 : public WriteAttribute {
public:
    WriteUnitTestingNullableEnum16()
        : WriteAttribute("nullable-enum16")
    {
        AddArgument("attr-name", "nullable-enum16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableEnum16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeNullableEnum16WithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting NullableEnum16 write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeUnitTestingNullableEnum16 : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableEnum16()
        : SubscribeAttribute("nullable-enum16")
    {
    }

    ~SubscribeAttributeUnitTestingNullableEnum16() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableEnum16WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableEnum16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableFloatSingle
 */
class ReadUnitTestingNullableFloatSingle : public ReadAttribute {
public:
    ReadUnitTestingNullableFloatSingle()
        : ReadAttribute("nullable-float-single")
    {
    }

    ~ReadUnitTestingNullableFloatSingle() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableFloatSingleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableFloatSingle response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableFloatSingle read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableFloatSingle : public WriteAttribute {
public:
    WriteUnitTestingNullableFloatSingle()
        : 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();
    }

    ~WriteUnitTestingNullableFloatSingle() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithFloat:mValue];

        [cluster writeAttributeNullableFloatSingleWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("UnitTesting NullableFloatSingle write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    float mValue;
};

class SubscribeAttributeUnitTestingNullableFloatSingle : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableFloatSingle()
        : SubscribeAttribute("nullable-float-single")
    {
    }

    ~SubscribeAttributeUnitTestingNullableFloatSingle() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableFloatSingleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableFloatSingle response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableFloatDouble
 */
class ReadUnitTestingNullableFloatDouble : public ReadAttribute {
public:
    ReadUnitTestingNullableFloatDouble()
        : ReadAttribute("nullable-float-double")
    {
    }

    ~ReadUnitTestingNullableFloatDouble() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableFloatDoubleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableFloatDouble response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableFloatDouble read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableFloatDouble : public WriteAttribute {
public:
    WriteUnitTestingNullableFloatDouble()
        : 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();
    }

    ~WriteUnitTestingNullableFloatDouble() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithDouble:mValue];

        [cluster writeAttributeNullableFloatDoubleWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("UnitTesting NullableFloatDouble write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    double mValue;
};

class SubscribeAttributeUnitTestingNullableFloatDouble : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableFloatDouble()
        : SubscribeAttribute("nullable-float-double")
    {
    }

    ~SubscribeAttributeUnitTestingNullableFloatDouble() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableFloatDoubleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableFloatDouble response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableOctetString
 */
class ReadUnitTestingNullableOctetString : public ReadAttribute {
public:
    ReadUnitTestingNullableOctetString()
        : ReadAttribute("nullable-octet-string")
    {
    }

    ~ReadUnitTestingNullableOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableOctetStringWithCompletion:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableOctetString : public WriteAttribute {
public:
    WriteUnitTestingNullableOctetString()
        : WriteAttribute("nullable-octet-string")
    {
        AddArgument("attr-name", "nullable-octet-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSData * _Nullable value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()];

        [cluster writeAttributeNullableOctetStringWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("UnitTesting NullableOctetString write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeUnitTestingNullableOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableOctetString()
        : SubscribeAttribute("nullable-octet-string")
    {
    }

    ~SubscribeAttributeUnitTestingNullableOctetString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableCharString
 */
class ReadUnitTestingNullableCharString : public ReadAttribute {
public:
    ReadUnitTestingNullableCharString()
        : ReadAttribute("nullable-char-string")
    {
    }

    ~ReadUnitTestingNullableCharString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableCharStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableCharString response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableCharString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableCharString : public WriteAttribute {
public:
    WriteUnitTestingNullableCharString()
        : WriteAttribute("nullable-char-string")
    {
        AddArgument("attr-name", "nullable-char-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableCharString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        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("UnitTesting NullableCharString write Error", error);
                                                    }
                                                    SetCommandExitStatus(error);
                                                }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeUnitTestingNullableCharString : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableCharString()
        : SubscribeAttribute("nullable-char-string")
    {
    }

    ~SubscribeAttributeUnitTestingNullableCharString() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableCharStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableCharString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableEnumAttr
 */
class ReadUnitTestingNullableEnumAttr : public ReadAttribute {
public:
    ReadUnitTestingNullableEnumAttr()
        : ReadAttribute("nullable-enum-attr")
    {
    }

    ~ReadUnitTestingNullableEnumAttr() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableEnumAttrWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableEnumAttr response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableEnumAttr read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableEnumAttr : public WriteAttribute {
public:
    WriteUnitTestingNullableEnumAttr()
        : WriteAttribute("nullable-enum-attr")
    {
        AddArgument("attr-name", "nullable-enum-attr");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableEnumAttr() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableEnumAttrWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("UnitTesting NullableEnumAttr write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingNullableEnumAttr : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableEnumAttr()
        : SubscribeAttribute("nullable-enum-attr")
    {
    }

    ~SubscribeAttributeUnitTestingNullableEnumAttr() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableEnumAttrWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableEnumAttr response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableStruct
 */
class ReadUnitTestingNullableStruct : public ReadAttribute {
public:
    ReadUnitTestingNullableStruct()
        : ReadAttribute("nullable-struct")
    {
    }

    ~ReadUnitTestingNullableStruct() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableStructWithCompletion:^(
            MTRUnitTestingClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableStruct response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableStruct read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableStruct : public WriteAttribute {
public:
    WriteUnitTestingNullableStruct()
        : WriteAttribute("nullable-struct")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "nullable-struct");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableStruct() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        MTRUnitTestingClusterSimpleStruct * _Nullable value;
        if (mValue.IsNull()) {
            value = nil;
        } else {
            value = [MTRUnitTestingClusterSimpleStruct 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("UnitTesting NullableStruct write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::Nullable<chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::Nullable<chip::app::Clusters::UnitTesting::Structs::SimpleStruct::Type>> mComplex;
};

class SubscribeAttributeUnitTestingNullableStruct : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableStruct()
        : SubscribeAttribute("nullable-struct")
    {
    }

    ~SubscribeAttributeUnitTestingNullableStruct() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableStructWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRUnitTestingClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableStruct response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt8u
 */
class ReadUnitTestingNullableRangeRestrictedInt8u : public ReadAttribute {
public:
    ReadUnitTestingNullableRangeRestrictedInt8u()
        : ReadAttribute("nullable-range-restricted-int8u")
    {
    }

    ~ReadUnitTestingNullableRangeRestrictedInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableRangeRestrictedInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableRangeRestrictedInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableRangeRestrictedInt8u : public WriteAttribute {
public:
    WriteUnitTestingNullableRangeRestrictedInt8u()
        : WriteAttribute("nullable-range-restricted-int8u")
    {
        AddArgument("attr-name", "nullable-range-restricted-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableRangeRestrictedInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableRangeRestrictedInt8uWithValue:value
                                                              params:params
                                                          completion:^(NSError * _Nullable error) {
                                                              if (error != nil) {
                                                                  LogNSError("UnitTesting NullableRangeRestrictedInt8u write Error",
                                                                      error);
                                                              }
                                                              SetCommandExitStatus(error);
                                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingNullableRangeRestrictedInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableRangeRestrictedInt8u()
        : SubscribeAttribute("nullable-range-restricted-int8u")
    {
    }

    ~SubscribeAttributeUnitTestingNullableRangeRestrictedInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableRangeRestrictedInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableRangeRestrictedInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt8s
 */
class ReadUnitTestingNullableRangeRestrictedInt8s : public ReadAttribute {
public:
    ReadUnitTestingNullableRangeRestrictedInt8s()
        : ReadAttribute("nullable-range-restricted-int8s")
    {
    }

    ~ReadUnitTestingNullableRangeRestrictedInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt8sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableRangeRestrictedInt8s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableRangeRestrictedInt8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableRangeRestrictedInt8s : public WriteAttribute {
public:
    WriteUnitTestingNullableRangeRestrictedInt8s()
        : WriteAttribute("nullable-range-restricted-int8s")
    {
        AddArgument("attr-name", "nullable-range-restricted-int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableRangeRestrictedInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeNullableRangeRestrictedInt8sWithValue:value
                                                              params:params
                                                          completion:^(NSError * _Nullable error) {
                                                              if (error != nil) {
                                                                  LogNSError("UnitTesting NullableRangeRestrictedInt8s write Error",
                                                                      error);
                                                              }
                                                              SetCommandExitStatus(error);
                                                          }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeUnitTestingNullableRangeRestrictedInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableRangeRestrictedInt8s()
        : SubscribeAttribute("nullable-range-restricted-int8s")
    {
    }

    ~SubscribeAttributeUnitTestingNullableRangeRestrictedInt8s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableRangeRestrictedInt8sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableRangeRestrictedInt8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt16u
 */
class ReadUnitTestingNullableRangeRestrictedInt16u : public ReadAttribute {
public:
    ReadUnitTestingNullableRangeRestrictedInt16u()
        : ReadAttribute("nullable-range-restricted-int16u")
    {
    }

    ~ReadUnitTestingNullableRangeRestrictedInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt16uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableRangeRestrictedInt16u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableRangeRestrictedInt16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableRangeRestrictedInt16u : public WriteAttribute {
public:
    WriteUnitTestingNullableRangeRestrictedInt16u()
        : WriteAttribute("nullable-range-restricted-int16u")
    {
        AddArgument("attr-name", "nullable-range-restricted-int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableRangeRestrictedInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeNullableRangeRestrictedInt16uWithValue:value
                                                          params:params
                                                      completion:^(NSError * _Nullable error) {
                                                          if (error != nil) {
                                                              LogNSError(
                                                                  "UnitTesting NullableRangeRestrictedInt16u write Error", error);
                                                          }
                                                          SetCommandExitStatus(error);
                                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeUnitTestingNullableRangeRestrictedInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableRangeRestrictedInt16u()
        : SubscribeAttribute("nullable-range-restricted-int16u")
    {
    }

    ~SubscribeAttributeUnitTestingNullableRangeRestrictedInt16u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableRangeRestrictedInt16uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableRangeRestrictedInt16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt16s
 */
class ReadUnitTestingNullableRangeRestrictedInt16s : public ReadAttribute {
public:
    ReadUnitTestingNullableRangeRestrictedInt16s()
        : ReadAttribute("nullable-range-restricted-int16s")
    {
    }

    ~ReadUnitTestingNullableRangeRestrictedInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt16sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.NullableRangeRestrictedInt16s response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting NullableRangeRestrictedInt16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingNullableRangeRestrictedInt16s : public WriteAttribute {
public:
    WriteUnitTestingNullableRangeRestrictedInt16s()
        : WriteAttribute("nullable-range-restricted-int16s")
    {
        AddArgument("attr-name", "nullable-range-restricted-int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingNullableRangeRestrictedInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithShort:mValue];

        [cluster
            writeAttributeNullableRangeRestrictedInt16sWithValue:value
                                                          params:params
                                                      completion:^(NSError * _Nullable error) {
                                                          if (error != nil) {
                                                              LogNSError(
                                                                  "UnitTesting NullableRangeRestrictedInt16s write Error", error);
                                                          }
                                                          SetCommandExitStatus(error);
                                                      }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeUnitTestingNullableRangeRestrictedInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingNullableRangeRestrictedInt16s()
        : SubscribeAttribute("nullable-range-restricted-int16s")
    {
    }

    ~SubscribeAttributeUnitTestingNullableRangeRestrictedInt16s() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeNullableRangeRestrictedInt16sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.NullableRangeRestrictedInt16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WriteOnlyInt8u
 */
class ReadUnitTestingWriteOnlyInt8u : public ReadAttribute {
public:
    ReadUnitTestingWriteOnlyInt8u()
        : ReadAttribute("write-only-int8u")
    {
    }

    ~ReadUnitTestingWriteOnlyInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeWriteOnlyInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.WriteOnlyInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting WriteOnlyInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitTestingWriteOnlyInt8u : public WriteAttribute {
public:
    WriteUnitTestingWriteOnlyInt8u()
        : WriteAttribute("write-only-int8u")
    {
        AddArgument("attr-name", "write-only-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitTestingWriteOnlyInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeWriteOnlyInt8uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("UnitTesting WriteOnlyInt8u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitTestingWriteOnlyInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingWriteOnlyInt8u()
        : SubscribeAttribute("write-only-int8u")
    {
    }

    ~SubscribeAttributeUnitTestingWriteOnlyInt8u() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeWriteOnlyInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.WriteOnlyInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadUnitTestingGeneratedCommandList : public ReadAttribute {
public:
    ReadUnitTestingGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadUnitTestingGeneratedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitTestingGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeUnitTestingGeneratedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadUnitTestingAcceptedCommandList : public ReadAttribute {
public:
    ReadUnitTestingAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadUnitTestingAcceptedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitTestingAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeUnitTestingAcceptedCommandList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EventList
 */
class ReadUnitTestingEventList : public ReadAttribute {
public:
    ReadUnitTestingEventList()
        : ReadAttribute("event-list")
    {
    }

    ~ReadUnitTestingEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFFA) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeEventListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.EventList response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting EventList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitTestingEventList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingEventList()
        : SubscribeAttribute("event-list")
    {
    }

    ~SubscribeAttributeUnitTestingEventList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFFA) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeEventListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.EventList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadUnitTestingAttributeList : public ReadAttribute {
public:
    ReadUnitTestingAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadUnitTestingAttributeList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitTestingAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeUnitTestingAttributeList() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadUnitTestingFeatureMap : public ReadAttribute {
public:
    ReadUnitTestingFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadUnitTestingFeatureMap() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitTestingFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeUnitTestingFeatureMap() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadUnitTestingClusterRevision : public ReadAttribute {
public:
    ReadUnitTestingClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadUnitTestingClusterRevision() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitTesting.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitTesting ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitTestingClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeUnitTestingClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeUnitTestingClusterRevision() {}

    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);
        __auto_type * cluster = [[MTRBaseClusterUnitTesting alloc] initWithDevice:device
                                                                       endpointID:@(endpointId)
                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        if (mAutoResubscribe.HasValue()) {
            params.resubscribeAutomatically = mAutoResubscribe.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitTesting.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<ReadIdentifyEventList>(), //
        make_unique<SubscribeAttributeIdentifyEventList>(), //
        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<ReadGroupsEventList>(), //
        make_unique<SubscribeAttributeGroupsEventList>(), //
        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<ReadScenesEventList>(), //
        make_unique<SubscribeAttributeScenesEventList>(), //
        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<ReadOnOffEventList>(), //
        make_unique<SubscribeAttributeOnOffEventList>(), //
        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<ReadOnOffSwitchConfigurationEventList>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationEventList>(), //
        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<ReadLevelControlEventList>(), //
        make_unique<SubscribeAttributeLevelControlEventList>(), //
        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<ReadBinaryInputBasicEventList>(), //
        make_unique<SubscribeAttributeBinaryInputBasicEventList>(), //
        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<ReadDescriptorEventList>(), //
        make_unique<SubscribeAttributeDescriptorEventList>(), //
        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<ReadBindingEventList>(), //
        make_unique<SubscribeAttributeBindingEventList>(), //
        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<ReadAccessControlEventList>(), //
        make_unique<SubscribeAttributeAccessControlEventList>(), //
        make_unique<ReadAccessControlAttributeList>(), //
        make_unique<SubscribeAttributeAccessControlAttributeList>(), //
        make_unique<ReadAccessControlFeatureMap>(), //
        make_unique<SubscribeAttributeAccessControlFeatureMap>(), //
        make_unique<ReadAccessControlClusterRevision>(), //
        make_unique<SubscribeAttributeAccessControlClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadActionsEventList>(), //
        make_unique<SubscribeAttributeActionsEventList>(), //
        make_unique<ReadActionsAttributeList>(), //
        make_unique<SubscribeAttributeActionsAttributeList>(), //
        make_unique<ReadActionsFeatureMap>(), //
        make_unique<SubscribeAttributeActionsFeatureMap>(), //
        make_unique<ReadActionsClusterRevision>(), //
        make_unique<SubscribeAttributeActionsClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBasicInformation(Commands & commands)
{
    using namespace chip::app::Clusters::BasicInformation;

    const char * clusterName = "BasicInformation";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBasicInformationDataModelRevision>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBasicInformationDataModelRevision>(), //
        make_unique<ReadBasicInformationVendorName>(), //
        make_unique<SubscribeAttributeBasicInformationVendorName>(), //
        make_unique<ReadBasicInformationVendorID>(), //
        make_unique<SubscribeAttributeBasicInformationVendorID>(), //
        make_unique<ReadBasicInformationProductName>(), //
        make_unique<SubscribeAttributeBasicInformationProductName>(), //
        make_unique<ReadBasicInformationProductID>(), //
        make_unique<SubscribeAttributeBasicInformationProductID>(), //
        make_unique<ReadBasicInformationNodeLabel>(), //
        make_unique<WriteBasicInformationNodeLabel>(), //
        make_unique<SubscribeAttributeBasicInformationNodeLabel>(), //
        make_unique<ReadBasicInformationLocation>(), //
        make_unique<WriteBasicInformationLocation>(), //
        make_unique<SubscribeAttributeBasicInformationLocation>(), //
        make_unique<ReadBasicInformationHardwareVersion>(), //
        make_unique<SubscribeAttributeBasicInformationHardwareVersion>(), //
        make_unique<ReadBasicInformationHardwareVersionString>(), //
        make_unique<SubscribeAttributeBasicInformationHardwareVersionString>(), //
        make_unique<ReadBasicInformationSoftwareVersion>(), //
        make_unique<SubscribeAttributeBasicInformationSoftwareVersion>(), //
        make_unique<ReadBasicInformationSoftwareVersionString>(), //
        make_unique<SubscribeAttributeBasicInformationSoftwareVersionString>(), //
        make_unique<ReadBasicInformationManufacturingDate>(), //
        make_unique<SubscribeAttributeBasicInformationManufacturingDate>(), //
        make_unique<ReadBasicInformationPartNumber>(), //
        make_unique<SubscribeAttributeBasicInformationPartNumber>(), //
        make_unique<ReadBasicInformationProductURL>(), //
        make_unique<SubscribeAttributeBasicInformationProductURL>(), //
        make_unique<ReadBasicInformationProductLabel>(), //
        make_unique<SubscribeAttributeBasicInformationProductLabel>(), //
        make_unique<ReadBasicInformationSerialNumber>(), //
        make_unique<SubscribeAttributeBasicInformationSerialNumber>(), //
        make_unique<ReadBasicInformationLocalConfigDisabled>(), //
        make_unique<WriteBasicInformationLocalConfigDisabled>(), //
        make_unique<SubscribeAttributeBasicInformationLocalConfigDisabled>(), //
        make_unique<ReadBasicInformationReachable>(), //
        make_unique<SubscribeAttributeBasicInformationReachable>(), //
        make_unique<ReadBasicInformationUniqueID>(), //
        make_unique<SubscribeAttributeBasicInformationUniqueID>(), //
        make_unique<ReadBasicInformationCapabilityMinima>(), //
        make_unique<SubscribeAttributeBasicInformationCapabilityMinima>(), //
        make_unique<ReadBasicInformationProductAppearance>(), //
        make_unique<SubscribeAttributeBasicInformationProductAppearance>(), //
        make_unique<ReadBasicInformationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBasicInformationGeneratedCommandList>(), //
        make_unique<ReadBasicInformationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBasicInformationAcceptedCommandList>(), //
        make_unique<ReadBasicInformationEventList>(), //
        make_unique<SubscribeAttributeBasicInformationEventList>(), //
        make_unique<ReadBasicInformationAttributeList>(), //
        make_unique<SubscribeAttributeBasicInformationAttributeList>(), //
        make_unique<ReadBasicInformationFeatureMap>(), //
        make_unique<SubscribeAttributeBasicInformationFeatureMap>(), //
        make_unique<ReadBasicInformationClusterRevision>(), //
        make_unique<SubscribeAttributeBasicInformationClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadOtaSoftwareUpdateProviderEventList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderEventList>(), //
        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<ReadOtaSoftwareUpdateRequestorEventList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorEventList>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorAttributeList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorAttributeList>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorFeatureMap>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorFeatureMap>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorClusterRevision>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadLocalizationConfigurationEventList>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationEventList>(), //
        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<ReadTimeFormatLocalizationEventList>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationEventList>(), //
        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<ReadUnitLocalizationEventList>(), //
        make_unique<SubscribeAttributeUnitLocalizationEventList>(), //
        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<ReadPowerSourceConfigurationEventList>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationEventList>(), //
        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<ReadPowerSourceEventList>(), //
        make_unique<SubscribeAttributePowerSourceEventList>(), //
        make_unique<ReadPowerSourceAttributeList>(), //
        make_unique<SubscribeAttributePowerSourceAttributeList>(), //
        make_unique<ReadPowerSourceFeatureMap>(), //
        make_unique<SubscribeAttributePowerSourceFeatureMap>(), //
        make_unique<ReadPowerSourceClusterRevision>(), //
        make_unique<SubscribeAttributePowerSourceClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadGeneralCommissioningEventList>(), //
        make_unique<SubscribeAttributeGeneralCommissioningEventList>(), //
        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<ReadNetworkCommissioningEventList>(), //
        make_unique<SubscribeAttributeNetworkCommissioningEventList>(), //
        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<ReadDiagnosticLogsEventList>(), //
        make_unique<SubscribeAttributeDiagnosticLogsEventList>(), //
        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<ReadGeneralDiagnosticsBootReason>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsBootReason>(), //
        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<ReadGeneralDiagnosticsEventList>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsEventList>(), //
        make_unique<ReadGeneralDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsAttributeList>(), //
        make_unique<ReadGeneralDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsFeatureMap>(), //
        make_unique<ReadGeneralDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadSoftwareDiagnosticsEventList>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsEventList>(), //
        make_unique<ReadSoftwareDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsAttributeList>(), //
        make_unique<ReadSoftwareDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsFeatureMap>(), //
        make_unique<ReadSoftwareDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadThreadNetworkDiagnosticsNeighborTable>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsNeighborTable>(), //
        make_unique<ReadThreadNetworkDiagnosticsRouteTable>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRouteTable>(), //
        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<ReadThreadNetworkDiagnosticsEventList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsEventList>(), //
        make_unique<ReadThreadNetworkDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsAttributeList>(), //
        make_unique<ReadThreadNetworkDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsFeatureMap>(), //
        make_unique<ReadThreadNetworkDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadWiFiNetworkDiagnosticsEventList>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsEventList>(), //
        make_unique<ReadWiFiNetworkDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsAttributeList>(), //
        make_unique<ReadWiFiNetworkDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsFeatureMap>(), //
        make_unique<ReadWiFiNetworkDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadEthernetNetworkDiagnosticsEventList>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsEventList>(), //
        make_unique<ReadEthernetNetworkDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsAttributeList>(), //
        make_unique<ReadEthernetNetworkDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsFeatureMap>(), //
        make_unique<ReadEthernetNetworkDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBridgedDeviceBasicInformation(Commands & commands)
{
    using namespace chip::app::Clusters::BridgedDeviceBasicInformation;

    const char * clusterName = "BridgedDeviceBasicInformation";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBridgedDeviceBasicInformationVendorName>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationVendorName>(), //
        make_unique<ReadBridgedDeviceBasicInformationVendorID>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationVendorID>(), //
        make_unique<ReadBridgedDeviceBasicInformationProductName>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationProductName>(), //
        make_unique<ReadBridgedDeviceBasicInformationNodeLabel>(), //
        make_unique<WriteBridgedDeviceBasicInformationNodeLabel>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationNodeLabel>(), //
        make_unique<ReadBridgedDeviceBasicInformationHardwareVersion>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationHardwareVersion>(), //
        make_unique<ReadBridgedDeviceBasicInformationHardwareVersionString>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationHardwareVersionString>(), //
        make_unique<ReadBridgedDeviceBasicInformationSoftwareVersion>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationSoftwareVersion>(), //
        make_unique<ReadBridgedDeviceBasicInformationSoftwareVersionString>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationSoftwareVersionString>(), //
        make_unique<ReadBridgedDeviceBasicInformationManufacturingDate>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationManufacturingDate>(), //
        make_unique<ReadBridgedDeviceBasicInformationPartNumber>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationPartNumber>(), //
        make_unique<ReadBridgedDeviceBasicInformationProductURL>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationProductURL>(), //
        make_unique<ReadBridgedDeviceBasicInformationProductLabel>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationProductLabel>(), //
        make_unique<ReadBridgedDeviceBasicInformationSerialNumber>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationSerialNumber>(), //
        make_unique<ReadBridgedDeviceBasicInformationReachable>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationReachable>(), //
        make_unique<ReadBridgedDeviceBasicInformationUniqueID>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationUniqueID>(), //
        make_unique<ReadBridgedDeviceBasicInformationProductAppearance>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationProductAppearance>(), //
        make_unique<ReadBridgedDeviceBasicInformationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationGeneratedCommandList>(), //
        make_unique<ReadBridgedDeviceBasicInformationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationAcceptedCommandList>(), //
        make_unique<ReadBridgedDeviceBasicInformationEventList>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationEventList>(), //
        make_unique<ReadBridgedDeviceBasicInformationAttributeList>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationAttributeList>(), //
        make_unique<ReadBridgedDeviceBasicInformationFeatureMap>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationFeatureMap>(), //
        make_unique<ReadBridgedDeviceBasicInformationClusterRevision>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicInformationClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadSwitchEventList>(), //
        make_unique<SubscribeAttributeSwitchEventList>(), //
        make_unique<ReadSwitchAttributeList>(), //
        make_unique<SubscribeAttributeSwitchAttributeList>(), //
        make_unique<ReadSwitchFeatureMap>(), //
        make_unique<SubscribeAttributeSwitchFeatureMap>(), //
        make_unique<ReadSwitchClusterRevision>(), //
        make_unique<SubscribeAttributeSwitchClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadAdministratorCommissioningEventList>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningEventList>(), //
        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<ReadOperationalCredentialsEventList>(), //
        make_unique<SubscribeAttributeOperationalCredentialsEventList>(), //
        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<ReadGroupKeyManagementEventList>(), //
        make_unique<SubscribeAttributeGroupKeyManagementEventList>(), //
        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<ReadFixedLabelEventList>(), //
        make_unique<SubscribeAttributeFixedLabelEventList>(), //
        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<ReadUserLabelEventList>(), //
        make_unique<SubscribeAttributeUserLabelEventList>(), //
        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<ReadBooleanStateEventList>(), //
        make_unique<SubscribeAttributeBooleanStateEventList>(), //
        make_unique<ReadBooleanStateAttributeList>(), //
        make_unique<SubscribeAttributeBooleanStateAttributeList>(), //
        make_unique<ReadBooleanStateFeatureMap>(), //
        make_unique<SubscribeAttributeBooleanStateFeatureMap>(), //
        make_unique<ReadBooleanStateClusterRevision>(), //
        make_unique<SubscribeAttributeBooleanStateClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadModeSelectEventList>(), //
        make_unique<SubscribeAttributeModeSelectEventList>(), //
        make_unique<ReadModeSelectAttributeList>(), //
        make_unique<SubscribeAttributeModeSelectAttributeList>(), //
        make_unique<ReadModeSelectFeatureMap>(), //
        make_unique<SubscribeAttributeModeSelectFeatureMap>(), //
        make_unique<ReadModeSelectClusterRevision>(), //
        make_unique<SubscribeAttributeModeSelectClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterTemperatureControl(Commands & commands)
{
    using namespace chip::app::Clusters::TemperatureControl;

    const char * clusterName = "TemperatureControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<TemperatureControlSetTemperature>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadTemperatureControlTemperatureSetpoint>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeTemperatureControlTemperatureSetpoint>(), //
        make_unique<ReadTemperatureControlMinTemperature>(), //
        make_unique<SubscribeAttributeTemperatureControlMinTemperature>(), //
        make_unique<ReadTemperatureControlMaxTemperature>(), //
        make_unique<SubscribeAttributeTemperatureControlMaxTemperature>(), //
        make_unique<ReadTemperatureControlStep>(), //
        make_unique<SubscribeAttributeTemperatureControlStep>(), //
        make_unique<ReadTemperatureControlCurrentTemperatureLevelIndex>(), //
        make_unique<SubscribeAttributeTemperatureControlCurrentTemperatureLevelIndex>(), //
        make_unique<ReadTemperatureControlSupportedTemperatureLevels>(), //
        make_unique<SubscribeAttributeTemperatureControlSupportedTemperatureLevels>(), //
        make_unique<ReadTemperatureControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeTemperatureControlGeneratedCommandList>(), //
        make_unique<ReadTemperatureControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeTemperatureControlAcceptedCommandList>(), //
        make_unique<ReadTemperatureControlEventList>(), //
        make_unique<SubscribeAttributeTemperatureControlEventList>(), //
        make_unique<ReadTemperatureControlAttributeList>(), //
        make_unique<SubscribeAttributeTemperatureControlAttributeList>(), //
        make_unique<ReadTemperatureControlFeatureMap>(), //
        make_unique<SubscribeAttributeTemperatureControlFeatureMap>(), //
        make_unique<ReadTemperatureControlClusterRevision>(), //
        make_unique<SubscribeAttributeTemperatureControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterRefrigeratorAlarm(Commands & commands)
{
    using namespace chip::app::Clusters::RefrigeratorAlarm;

    const char * clusterName = "RefrigeratorAlarm";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<RefrigeratorAlarmReset>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadRefrigeratorAlarmMask>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteRefrigeratorAlarmMask>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeRefrigeratorAlarmMask>(), //
        make_unique<ReadRefrigeratorAlarmLatch>(), //
        make_unique<SubscribeAttributeRefrigeratorAlarmLatch>(), //
        make_unique<ReadRefrigeratorAlarmState>(), //
        make_unique<SubscribeAttributeRefrigeratorAlarmState>(), //
        make_unique<ReadRefrigeratorAlarmGeneratedCommandList>(), //
        make_unique<SubscribeAttributeRefrigeratorAlarmGeneratedCommandList>(), //
        make_unique<ReadRefrigeratorAlarmAcceptedCommandList>(), //
        make_unique<SubscribeAttributeRefrigeratorAlarmAcceptedCommandList>(), //
        make_unique<ReadRefrigeratorAlarmEventList>(), //
        make_unique<SubscribeAttributeRefrigeratorAlarmEventList>(), //
        make_unique<ReadRefrigeratorAlarmAttributeList>(), //
        make_unique<SubscribeAttributeRefrigeratorAlarmAttributeList>(), //
        make_unique<ReadRefrigeratorAlarmFeatureMap>(), //
        make_unique<SubscribeAttributeRefrigeratorAlarmFeatureMap>(), //
        make_unique<ReadRefrigeratorAlarmClusterRevision>(), //
        make_unique<SubscribeAttributeRefrigeratorAlarmClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterAirQuality(Commands & commands)
{
    using namespace chip::app::Clusters::AirQuality;

    const char * clusterName = "AirQuality";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadAirQualityAirQuality>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeAirQualityAirQuality>(), //
        make_unique<ReadAirQualityGeneratedCommandList>(), //
        make_unique<SubscribeAttributeAirQualityGeneratedCommandList>(), //
        make_unique<ReadAirQualityAcceptedCommandList>(), //
        make_unique<SubscribeAttributeAirQualityAcceptedCommandList>(), //
        make_unique<ReadAirQualityEventList>(), //
        make_unique<SubscribeAttributeAirQualityEventList>(), //
        make_unique<ReadAirQualityAttributeList>(), //
        make_unique<SubscribeAttributeAirQualityAttributeList>(), //
        make_unique<ReadAirQualityFeatureMap>(), //
        make_unique<SubscribeAttributeAirQualityFeatureMap>(), //
        make_unique<ReadAirQualityClusterRevision>(), //
        make_unique<SubscribeAttributeAirQualityClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterSmokeCoAlarm(Commands & commands)
{
    using namespace chip::app::Clusters::SmokeCoAlarm;

    const char * clusterName = "SmokeCoAlarm";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<SmokeCoAlarmSelfTestRequest>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadSmokeCoAlarmExpressedState>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeSmokeCoAlarmExpressedState>(), //
        make_unique<ReadSmokeCoAlarmSmokeState>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmSmokeState>(), //
        make_unique<ReadSmokeCoAlarmCOState>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmCOState>(), //
        make_unique<ReadSmokeCoAlarmBatteryAlert>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmBatteryAlert>(), //
        make_unique<ReadSmokeCoAlarmDeviceMuted>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmDeviceMuted>(), //
        make_unique<ReadSmokeCoAlarmTestInProgress>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmTestInProgress>(), //
        make_unique<ReadSmokeCoAlarmHardwareFaultAlert>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmHardwareFaultAlert>(), //
        make_unique<ReadSmokeCoAlarmEndOfServiceAlert>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmEndOfServiceAlert>(), //
        make_unique<ReadSmokeCoAlarmInterconnectSmokeAlarm>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmInterconnectSmokeAlarm>(), //
        make_unique<ReadSmokeCoAlarmInterconnectCOAlarm>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmInterconnectCOAlarm>(), //
        make_unique<ReadSmokeCoAlarmContaminationState>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmContaminationState>(), //
        make_unique<ReadSmokeCoAlarmSensitivityLevel>(), //
        make_unique<WriteSmokeCoAlarmSensitivityLevel>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmSensitivityLevel>(), //
        make_unique<ReadSmokeCoAlarmGeneratedCommandList>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmGeneratedCommandList>(), //
        make_unique<ReadSmokeCoAlarmAcceptedCommandList>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmAcceptedCommandList>(), //
        make_unique<ReadSmokeCoAlarmEventList>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmEventList>(), //
        make_unique<ReadSmokeCoAlarmAttributeList>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmAttributeList>(), //
        make_unique<ReadSmokeCoAlarmFeatureMap>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmFeatureMap>(), //
        make_unique<ReadSmokeCoAlarmClusterRevision>(), //
        make_unique<SubscribeAttributeSmokeCoAlarmClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterHepaFilterMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::HepaFilterMonitoring;

    const char * clusterName = "HepaFilterMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<HepaFilterMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadHepaFilterMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeHepaFilterMonitoringCondition>(), //
        make_unique<ReadHepaFilterMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeHepaFilterMonitoringDegradationDirection>(), //
        make_unique<ReadHepaFilterMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeHepaFilterMonitoringChangeIndication>(), //
        make_unique<ReadHepaFilterMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeHepaFilterMonitoringInPlaceIndicator>(), //
        make_unique<ReadHepaFilterMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeHepaFilterMonitoringGeneratedCommandList>(), //
        make_unique<ReadHepaFilterMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeHepaFilterMonitoringAcceptedCommandList>(), //
        make_unique<ReadHepaFilterMonitoringEventList>(), //
        make_unique<SubscribeAttributeHepaFilterMonitoringEventList>(), //
        make_unique<ReadHepaFilterMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeHepaFilterMonitoringAttributeList>(), //
        make_unique<ReadHepaFilterMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeHepaFilterMonitoringFeatureMap>(), //
        make_unique<ReadHepaFilterMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeHepaFilterMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterActivatedCarbonFilterMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::ActivatedCarbonFilterMonitoring;

    const char * clusterName = "ActivatedCarbonFilterMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ActivatedCarbonFilterMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadActivatedCarbonFilterMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeActivatedCarbonFilterMonitoringCondition>(), //
        make_unique<ReadActivatedCarbonFilterMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeActivatedCarbonFilterMonitoringDegradationDirection>(), //
        make_unique<ReadActivatedCarbonFilterMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeActivatedCarbonFilterMonitoringChangeIndication>(), //
        make_unique<ReadActivatedCarbonFilterMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeActivatedCarbonFilterMonitoringInPlaceIndicator>(), //
        make_unique<ReadActivatedCarbonFilterMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeActivatedCarbonFilterMonitoringGeneratedCommandList>(), //
        make_unique<ReadActivatedCarbonFilterMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeActivatedCarbonFilterMonitoringAcceptedCommandList>(), //
        make_unique<ReadActivatedCarbonFilterMonitoringEventList>(), //
        make_unique<SubscribeAttributeActivatedCarbonFilterMonitoringEventList>(), //
        make_unique<ReadActivatedCarbonFilterMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeActivatedCarbonFilterMonitoringAttributeList>(), //
        make_unique<ReadActivatedCarbonFilterMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeActivatedCarbonFilterMonitoringFeatureMap>(), //
        make_unique<ReadActivatedCarbonFilterMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeActivatedCarbonFilterMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterCeramicFilterMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::CeramicFilterMonitoring;

    const char * clusterName = "CeramicFilterMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<CeramicFilterMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadCeramicFilterMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeCeramicFilterMonitoringCondition>(), //
        make_unique<ReadCeramicFilterMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeCeramicFilterMonitoringDegradationDirection>(), //
        make_unique<ReadCeramicFilterMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeCeramicFilterMonitoringChangeIndication>(), //
        make_unique<ReadCeramicFilterMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeCeramicFilterMonitoringInPlaceIndicator>(), //
        make_unique<ReadCeramicFilterMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeCeramicFilterMonitoringGeneratedCommandList>(), //
        make_unique<ReadCeramicFilterMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeCeramicFilterMonitoringAcceptedCommandList>(), //
        make_unique<ReadCeramicFilterMonitoringEventList>(), //
        make_unique<SubscribeAttributeCeramicFilterMonitoringEventList>(), //
        make_unique<ReadCeramicFilterMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeCeramicFilterMonitoringAttributeList>(), //
        make_unique<ReadCeramicFilterMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeCeramicFilterMonitoringFeatureMap>(), //
        make_unique<ReadCeramicFilterMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeCeramicFilterMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterElectrostaticFilterMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::ElectrostaticFilterMonitoring;

    const char * clusterName = "ElectrostaticFilterMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ElectrostaticFilterMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadElectrostaticFilterMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeElectrostaticFilterMonitoringCondition>(), //
        make_unique<ReadElectrostaticFilterMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeElectrostaticFilterMonitoringDegradationDirection>(), //
        make_unique<ReadElectrostaticFilterMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeElectrostaticFilterMonitoringChangeIndication>(), //
        make_unique<ReadElectrostaticFilterMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeElectrostaticFilterMonitoringInPlaceIndicator>(), //
        make_unique<ReadElectrostaticFilterMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeElectrostaticFilterMonitoringGeneratedCommandList>(), //
        make_unique<ReadElectrostaticFilterMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeElectrostaticFilterMonitoringAcceptedCommandList>(), //
        make_unique<ReadElectrostaticFilterMonitoringEventList>(), //
        make_unique<SubscribeAttributeElectrostaticFilterMonitoringEventList>(), //
        make_unique<ReadElectrostaticFilterMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeElectrostaticFilterMonitoringAttributeList>(), //
        make_unique<ReadElectrostaticFilterMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeElectrostaticFilterMonitoringFeatureMap>(), //
        make_unique<ReadElectrostaticFilterMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeElectrostaticFilterMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterUvFilterMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::UvFilterMonitoring;

    const char * clusterName = "UvFilterMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<UvFilterMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadUvFilterMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeUvFilterMonitoringCondition>(), //
        make_unique<ReadUvFilterMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeUvFilterMonitoringDegradationDirection>(), //
        make_unique<ReadUvFilterMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeUvFilterMonitoringChangeIndication>(), //
        make_unique<ReadUvFilterMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeUvFilterMonitoringInPlaceIndicator>(), //
        make_unique<ReadUvFilterMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeUvFilterMonitoringGeneratedCommandList>(), //
        make_unique<ReadUvFilterMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeUvFilterMonitoringAcceptedCommandList>(), //
        make_unique<ReadUvFilterMonitoringEventList>(), //
        make_unique<SubscribeAttributeUvFilterMonitoringEventList>(), //
        make_unique<ReadUvFilterMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeUvFilterMonitoringAttributeList>(), //
        make_unique<ReadUvFilterMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeUvFilterMonitoringFeatureMap>(), //
        make_unique<ReadUvFilterMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeUvFilterMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterIonizingFilterMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::IonizingFilterMonitoring;

    const char * clusterName = "IonizingFilterMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<IonizingFilterMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadIonizingFilterMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeIonizingFilterMonitoringCondition>(), //
        make_unique<ReadIonizingFilterMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeIonizingFilterMonitoringDegradationDirection>(), //
        make_unique<ReadIonizingFilterMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeIonizingFilterMonitoringChangeIndication>(), //
        make_unique<ReadIonizingFilterMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeIonizingFilterMonitoringInPlaceIndicator>(), //
        make_unique<ReadIonizingFilterMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeIonizingFilterMonitoringGeneratedCommandList>(), //
        make_unique<ReadIonizingFilterMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeIonizingFilterMonitoringAcceptedCommandList>(), //
        make_unique<ReadIonizingFilterMonitoringEventList>(), //
        make_unique<SubscribeAttributeIonizingFilterMonitoringEventList>(), //
        make_unique<ReadIonizingFilterMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeIonizingFilterMonitoringAttributeList>(), //
        make_unique<ReadIonizingFilterMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeIonizingFilterMonitoringFeatureMap>(), //
        make_unique<ReadIonizingFilterMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeIonizingFilterMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterZeoliteFilterMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::ZeoliteFilterMonitoring;

    const char * clusterName = "ZeoliteFilterMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ZeoliteFilterMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadZeoliteFilterMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeZeoliteFilterMonitoringCondition>(), //
        make_unique<ReadZeoliteFilterMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeZeoliteFilterMonitoringDegradationDirection>(), //
        make_unique<ReadZeoliteFilterMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeZeoliteFilterMonitoringChangeIndication>(), //
        make_unique<ReadZeoliteFilterMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeZeoliteFilterMonitoringInPlaceIndicator>(), //
        make_unique<ReadZeoliteFilterMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeZeoliteFilterMonitoringGeneratedCommandList>(), //
        make_unique<ReadZeoliteFilterMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeZeoliteFilterMonitoringAcceptedCommandList>(), //
        make_unique<ReadZeoliteFilterMonitoringEventList>(), //
        make_unique<SubscribeAttributeZeoliteFilterMonitoringEventList>(), //
        make_unique<ReadZeoliteFilterMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeZeoliteFilterMonitoringAttributeList>(), //
        make_unique<ReadZeoliteFilterMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeZeoliteFilterMonitoringFeatureMap>(), //
        make_unique<ReadZeoliteFilterMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeZeoliteFilterMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOzoneFilterMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::OzoneFilterMonitoring;

    const char * clusterName = "OzoneFilterMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<OzoneFilterMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOzoneFilterMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOzoneFilterMonitoringCondition>(), //
        make_unique<ReadOzoneFilterMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeOzoneFilterMonitoringDegradationDirection>(), //
        make_unique<ReadOzoneFilterMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeOzoneFilterMonitoringChangeIndication>(), //
        make_unique<ReadOzoneFilterMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeOzoneFilterMonitoringInPlaceIndicator>(), //
        make_unique<ReadOzoneFilterMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOzoneFilterMonitoringGeneratedCommandList>(), //
        make_unique<ReadOzoneFilterMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOzoneFilterMonitoringAcceptedCommandList>(), //
        make_unique<ReadOzoneFilterMonitoringEventList>(), //
        make_unique<SubscribeAttributeOzoneFilterMonitoringEventList>(), //
        make_unique<ReadOzoneFilterMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeOzoneFilterMonitoringAttributeList>(), //
        make_unique<ReadOzoneFilterMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeOzoneFilterMonitoringFeatureMap>(), //
        make_unique<ReadOzoneFilterMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeOzoneFilterMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterWaterTankMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::WaterTankMonitoring;

    const char * clusterName = "WaterTankMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<WaterTankMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadWaterTankMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeWaterTankMonitoringCondition>(), //
        make_unique<ReadWaterTankMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeWaterTankMonitoringDegradationDirection>(), //
        make_unique<ReadWaterTankMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeWaterTankMonitoringChangeIndication>(), //
        make_unique<ReadWaterTankMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeWaterTankMonitoringInPlaceIndicator>(), //
        make_unique<ReadWaterTankMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeWaterTankMonitoringGeneratedCommandList>(), //
        make_unique<ReadWaterTankMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeWaterTankMonitoringAcceptedCommandList>(), //
        make_unique<ReadWaterTankMonitoringEventList>(), //
        make_unique<SubscribeAttributeWaterTankMonitoringEventList>(), //
        make_unique<ReadWaterTankMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeWaterTankMonitoringAttributeList>(), //
        make_unique<ReadWaterTankMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeWaterTankMonitoringFeatureMap>(), //
        make_unique<ReadWaterTankMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeWaterTankMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterFuelTankMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::FuelTankMonitoring;

    const char * clusterName = "FuelTankMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<FuelTankMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadFuelTankMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeFuelTankMonitoringCondition>(), //
        make_unique<ReadFuelTankMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeFuelTankMonitoringDegradationDirection>(), //
        make_unique<ReadFuelTankMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeFuelTankMonitoringChangeIndication>(), //
        make_unique<ReadFuelTankMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeFuelTankMonitoringInPlaceIndicator>(), //
        make_unique<ReadFuelTankMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeFuelTankMonitoringGeneratedCommandList>(), //
        make_unique<ReadFuelTankMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeFuelTankMonitoringAcceptedCommandList>(), //
        make_unique<ReadFuelTankMonitoringEventList>(), //
        make_unique<SubscribeAttributeFuelTankMonitoringEventList>(), //
        make_unique<ReadFuelTankMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeFuelTankMonitoringAttributeList>(), //
        make_unique<ReadFuelTankMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeFuelTankMonitoringFeatureMap>(), //
        make_unique<ReadFuelTankMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeFuelTankMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterInkCartridgeMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::InkCartridgeMonitoring;

    const char * clusterName = "InkCartridgeMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<InkCartridgeMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadInkCartridgeMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeInkCartridgeMonitoringCondition>(), //
        make_unique<ReadInkCartridgeMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeInkCartridgeMonitoringDegradationDirection>(), //
        make_unique<ReadInkCartridgeMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeInkCartridgeMonitoringChangeIndication>(), //
        make_unique<ReadInkCartridgeMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeInkCartridgeMonitoringInPlaceIndicator>(), //
        make_unique<ReadInkCartridgeMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeInkCartridgeMonitoringGeneratedCommandList>(), //
        make_unique<ReadInkCartridgeMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeInkCartridgeMonitoringAcceptedCommandList>(), //
        make_unique<ReadInkCartridgeMonitoringEventList>(), //
        make_unique<SubscribeAttributeInkCartridgeMonitoringEventList>(), //
        make_unique<ReadInkCartridgeMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeInkCartridgeMonitoringAttributeList>(), //
        make_unique<ReadInkCartridgeMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeInkCartridgeMonitoringFeatureMap>(), //
        make_unique<ReadInkCartridgeMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeInkCartridgeMonitoringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterTonerCartridgeMonitoring(Commands & commands)
{
    using namespace chip::app::Clusters::TonerCartridgeMonitoring;

    const char * clusterName = "TonerCartridgeMonitoring";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<TonerCartridgeMonitoringResetCondition>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadTonerCartridgeMonitoringCondition>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeTonerCartridgeMonitoringCondition>(), //
        make_unique<ReadTonerCartridgeMonitoringDegradationDirection>(), //
        make_unique<SubscribeAttributeTonerCartridgeMonitoringDegradationDirection>(), //
        make_unique<ReadTonerCartridgeMonitoringChangeIndication>(), //
        make_unique<SubscribeAttributeTonerCartridgeMonitoringChangeIndication>(), //
        make_unique<ReadTonerCartridgeMonitoringInPlaceIndicator>(), //
        make_unique<SubscribeAttributeTonerCartridgeMonitoringInPlaceIndicator>(), //
        make_unique<ReadTonerCartridgeMonitoringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeTonerCartridgeMonitoringGeneratedCommandList>(), //
        make_unique<ReadTonerCartridgeMonitoringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeTonerCartridgeMonitoringAcceptedCommandList>(), //
        make_unique<ReadTonerCartridgeMonitoringEventList>(), //
        make_unique<SubscribeAttributeTonerCartridgeMonitoringEventList>(), //
        make_unique<ReadTonerCartridgeMonitoringAttributeList>(), //
        make_unique<SubscribeAttributeTonerCartridgeMonitoringAttributeList>(), //
        make_unique<ReadTonerCartridgeMonitoringFeatureMap>(), //
        make_unique<SubscribeAttributeTonerCartridgeMonitoringFeatureMap>(), //
        make_unique<ReadTonerCartridgeMonitoringClusterRevision>(), //
        make_unique<SubscribeAttributeTonerCartridgeMonitoringClusterRevision>(), //
    };

    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<DoorLockUnboltDoor>(), //
        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<ReadDoorLockEventList>(), //
        make_unique<SubscribeAttributeDoorLockEventList>(), //
        make_unique<ReadDoorLockAttributeList>(), //
        make_unique<SubscribeAttributeDoorLockAttributeList>(), //
        make_unique<ReadDoorLockFeatureMap>(), //
        make_unique<SubscribeAttributeDoorLockFeatureMap>(), //
        make_unique<ReadDoorLockClusterRevision>(), //
        make_unique<SubscribeAttributeDoorLockClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadWindowCoveringEventList>(), //
        make_unique<SubscribeAttributeWindowCoveringEventList>(), //
        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<ReadBarrierControlEventList>(), //
        make_unique<SubscribeAttributeBarrierControlEventList>(), //
        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<ReadPumpConfigurationAndControlEventList>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlEventList>(), //
        make_unique<ReadPumpConfigurationAndControlAttributeList>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlAttributeList>(), //
        make_unique<ReadPumpConfigurationAndControlFeatureMap>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlFeatureMap>(), //
        make_unique<ReadPumpConfigurationAndControlClusterRevision>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadThermostatEventList>(), //
        make_unique<SubscribeAttributeThermostatEventList>(), //
        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<ReadFanControlEventList>(), //
        make_unique<SubscribeAttributeFanControlEventList>(), //
        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<ReadThermostatUserInterfaceConfigurationEventList>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationEventList>(), //
        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<ReadColorControlEventList>(), //
        make_unique<SubscribeAttributeColorControlEventList>(), //
        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<ReadBallastConfigurationIntrinsicBallastFactor>(), //
        make_unique<WriteBallastConfigurationIntrinsicBallastFactor>(), //
        make_unique<SubscribeAttributeBallastConfigurationIntrinsicBallastFactor>(), //
        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<ReadBallastConfigurationEventList>(), //
        make_unique<SubscribeAttributeBallastConfigurationEventList>(), //
        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<ReadIlluminanceMeasurementEventList>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementEventList>(), //
        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<ReadTemperatureMeasurementEventList>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementEventList>(), //
        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<ReadPressureMeasurementEventList>(), //
        make_unique<SubscribeAttributePressureMeasurementEventList>(), //
        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<ReadFlowMeasurementEventList>(), //
        make_unique<SubscribeAttributeFlowMeasurementEventList>(), //
        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<ReadRelativeHumidityMeasurementEventList>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementEventList>(), //
        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<ReadOccupancySensingEventList>(), //
        make_unique<SubscribeAttributeOccupancySensingEventList>(), //
        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<ReadWakeOnLanEventList>(), //
        make_unique<SubscribeAttributeWakeOnLanEventList>(), //
        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<ReadChannelEventList>(), //
        make_unique<SubscribeAttributeChannelEventList>(), //
        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<ReadTargetNavigatorEventList>(), //
        make_unique<SubscribeAttributeTargetNavigatorEventList>(), //
        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<MediaPlaybackStop>(), //
        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<ReadMediaPlaybackEventList>(), //
        make_unique<SubscribeAttributeMediaPlaybackEventList>(), //
        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<ReadMediaInputEventList>(), //
        make_unique<SubscribeAttributeMediaInputEventList>(), //
        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<ReadLowPowerEventList>(), //
        make_unique<SubscribeAttributeLowPowerEventList>(), //
        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<ReadKeypadInputEventList>(), //
        make_unique<SubscribeAttributeKeypadInputEventList>(), //
        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<ReadContentLauncherEventList>(), //
        make_unique<SubscribeAttributeContentLauncherEventList>(), //
        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<ReadAudioOutputEventList>(), //
        make_unique<SubscribeAttributeAudioOutputEventList>(), //
        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<ReadApplicationLauncherEventList>(), //
        make_unique<SubscribeAttributeApplicationLauncherEventList>(), //
        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<ReadApplicationBasicEventList>(), //
        make_unique<SubscribeAttributeApplicationBasicEventList>(), //
        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<ReadAccountLoginEventList>(), //
        make_unique<SubscribeAttributeAccountLoginEventList>(), //
        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<ReadElectricalMeasurementEventList>(), //
        make_unique<SubscribeAttributeElectricalMeasurementEventList>(), //
        make_unique<ReadElectricalMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAttributeList>(), //
        make_unique<ReadElectricalMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeElectricalMeasurementFeatureMap>(), //
        make_unique<ReadElectricalMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeElectricalMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterUnitTesting(Commands & commands)
{
    using namespace chip::app::Clusters::UnitTesting;

    const char * clusterName = "UnitTesting";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<UnitTestingTest>(), //
        make_unique<UnitTestingTestNotHandled>(), //
        make_unique<UnitTestingTestSpecific>(), //
        make_unique<UnitTestingTestUnknownCommand>(), //
        make_unique<UnitTestingTestAddArguments>(), //
        make_unique<UnitTestingTestSimpleArgumentRequest>(), //
        make_unique<UnitTestingTestStructArrayArgumentRequest>(), //
        make_unique<UnitTestingTestStructArgumentRequest>(), //
        make_unique<UnitTestingTestNestedStructArgumentRequest>(), //
        make_unique<UnitTestingTestListStructArgumentRequest>(), //
        make_unique<UnitTestingTestListInt8UArgumentRequest>(), //
        make_unique<UnitTestingTestNestedStructListArgumentRequest>(), //
        make_unique<UnitTestingTestListNestedStructListArgumentRequest>(), //
        make_unique<UnitTestingTestListInt8UReverseRequest>(), //
        make_unique<UnitTestingTestEnumsRequest>(), //
        make_unique<UnitTestingTestNullableOptionalRequest>(), //
        make_unique<UnitTestingTestComplexNullableOptionalRequest>(), //
        make_unique<UnitTestingSimpleStructEchoRequest>(), //
        make_unique<UnitTestingTimedInvokeRequest>(), //
        make_unique<UnitTestingTestSimpleOptionalArgumentRequest>(), //
        make_unique<UnitTestingTestEmitTestEventRequest>(), //
        make_unique<UnitTestingTestEmitTestFabricScopedEventRequest>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadUnitTestingBoolean>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteUnitTestingBoolean>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeUnitTestingBoolean>(), //
        make_unique<ReadUnitTestingBitmap8>(), //
        make_unique<WriteUnitTestingBitmap8>(), //
        make_unique<SubscribeAttributeUnitTestingBitmap8>(), //
        make_unique<ReadUnitTestingBitmap16>(), //
        make_unique<WriteUnitTestingBitmap16>(), //
        make_unique<SubscribeAttributeUnitTestingBitmap16>(), //
        make_unique<ReadUnitTestingBitmap32>(), //
        make_unique<WriteUnitTestingBitmap32>(), //
        make_unique<SubscribeAttributeUnitTestingBitmap32>(), //
        make_unique<ReadUnitTestingBitmap64>(), //
        make_unique<WriteUnitTestingBitmap64>(), //
        make_unique<SubscribeAttributeUnitTestingBitmap64>(), //
        make_unique<ReadUnitTestingInt8u>(), //
        make_unique<WriteUnitTestingInt8u>(), //
        make_unique<SubscribeAttributeUnitTestingInt8u>(), //
        make_unique<ReadUnitTestingInt16u>(), //
        make_unique<WriteUnitTestingInt16u>(), //
        make_unique<SubscribeAttributeUnitTestingInt16u>(), //
        make_unique<ReadUnitTestingInt24u>(), //
        make_unique<WriteUnitTestingInt24u>(), //
        make_unique<SubscribeAttributeUnitTestingInt24u>(), //
        make_unique<ReadUnitTestingInt32u>(), //
        make_unique<WriteUnitTestingInt32u>(), //
        make_unique<SubscribeAttributeUnitTestingInt32u>(), //
        make_unique<ReadUnitTestingInt40u>(), //
        make_unique<WriteUnitTestingInt40u>(), //
        make_unique<SubscribeAttributeUnitTestingInt40u>(), //
        make_unique<ReadUnitTestingInt48u>(), //
        make_unique<WriteUnitTestingInt48u>(), //
        make_unique<SubscribeAttributeUnitTestingInt48u>(), //
        make_unique<ReadUnitTestingInt56u>(), //
        make_unique<WriteUnitTestingInt56u>(), //
        make_unique<SubscribeAttributeUnitTestingInt56u>(), //
        make_unique<ReadUnitTestingInt64u>(), //
        make_unique<WriteUnitTestingInt64u>(), //
        make_unique<SubscribeAttributeUnitTestingInt64u>(), //
        make_unique<ReadUnitTestingInt8s>(), //
        make_unique<WriteUnitTestingInt8s>(), //
        make_unique<SubscribeAttributeUnitTestingInt8s>(), //
        make_unique<ReadUnitTestingInt16s>(), //
        make_unique<WriteUnitTestingInt16s>(), //
        make_unique<SubscribeAttributeUnitTestingInt16s>(), //
        make_unique<ReadUnitTestingInt24s>(), //
        make_unique<WriteUnitTestingInt24s>(), //
        make_unique<SubscribeAttributeUnitTestingInt24s>(), //
        make_unique<ReadUnitTestingInt32s>(), //
        make_unique<WriteUnitTestingInt32s>(), //
        make_unique<SubscribeAttributeUnitTestingInt32s>(), //
        make_unique<ReadUnitTestingInt40s>(), //
        make_unique<WriteUnitTestingInt40s>(), //
        make_unique<SubscribeAttributeUnitTestingInt40s>(), //
        make_unique<ReadUnitTestingInt48s>(), //
        make_unique<WriteUnitTestingInt48s>(), //
        make_unique<SubscribeAttributeUnitTestingInt48s>(), //
        make_unique<ReadUnitTestingInt56s>(), //
        make_unique<WriteUnitTestingInt56s>(), //
        make_unique<SubscribeAttributeUnitTestingInt56s>(), //
        make_unique<ReadUnitTestingInt64s>(), //
        make_unique<WriteUnitTestingInt64s>(), //
        make_unique<SubscribeAttributeUnitTestingInt64s>(), //
        make_unique<ReadUnitTestingEnum8>(), //
        make_unique<WriteUnitTestingEnum8>(), //
        make_unique<SubscribeAttributeUnitTestingEnum8>(), //
        make_unique<ReadUnitTestingEnum16>(), //
        make_unique<WriteUnitTestingEnum16>(), //
        make_unique<SubscribeAttributeUnitTestingEnum16>(), //
        make_unique<ReadUnitTestingFloatSingle>(), //
        make_unique<WriteUnitTestingFloatSingle>(), //
        make_unique<SubscribeAttributeUnitTestingFloatSingle>(), //
        make_unique<ReadUnitTestingFloatDouble>(), //
        make_unique<WriteUnitTestingFloatDouble>(), //
        make_unique<SubscribeAttributeUnitTestingFloatDouble>(), //
        make_unique<ReadUnitTestingOctetString>(), //
        make_unique<WriteUnitTestingOctetString>(), //
        make_unique<SubscribeAttributeUnitTestingOctetString>(), //
        make_unique<ReadUnitTestingListInt8u>(), //
        make_unique<WriteUnitTestingListInt8u>(), //
        make_unique<SubscribeAttributeUnitTestingListInt8u>(), //
        make_unique<ReadUnitTestingListOctetString>(), //
        make_unique<WriteUnitTestingListOctetString>(), //
        make_unique<SubscribeAttributeUnitTestingListOctetString>(), //
        make_unique<ReadUnitTestingListStructOctetString>(), //
        make_unique<WriteUnitTestingListStructOctetString>(), //
        make_unique<SubscribeAttributeUnitTestingListStructOctetString>(), //
        make_unique<ReadUnitTestingLongOctetString>(), //
        make_unique<WriteUnitTestingLongOctetString>(), //
        make_unique<SubscribeAttributeUnitTestingLongOctetString>(), //
        make_unique<ReadUnitTestingCharString>(), //
        make_unique<WriteUnitTestingCharString>(), //
        make_unique<SubscribeAttributeUnitTestingCharString>(), //
        make_unique<ReadUnitTestingLongCharString>(), //
        make_unique<WriteUnitTestingLongCharString>(), //
        make_unique<SubscribeAttributeUnitTestingLongCharString>(), //
        make_unique<ReadUnitTestingEpochUs>(), //
        make_unique<WriteUnitTestingEpochUs>(), //
        make_unique<SubscribeAttributeUnitTestingEpochUs>(), //
        make_unique<ReadUnitTestingEpochS>(), //
        make_unique<WriteUnitTestingEpochS>(), //
        make_unique<SubscribeAttributeUnitTestingEpochS>(), //
        make_unique<ReadUnitTestingVendorId>(), //
        make_unique<WriteUnitTestingVendorId>(), //
        make_unique<SubscribeAttributeUnitTestingVendorId>(), //
        make_unique<ReadUnitTestingListNullablesAndOptionalsStruct>(), //
        make_unique<WriteUnitTestingListNullablesAndOptionalsStruct>(), //
        make_unique<SubscribeAttributeUnitTestingListNullablesAndOptionalsStruct>(), //
        make_unique<ReadUnitTestingEnumAttr>(), //
        make_unique<WriteUnitTestingEnumAttr>(), //
        make_unique<SubscribeAttributeUnitTestingEnumAttr>(), //
        make_unique<ReadUnitTestingStructAttr>(), //
        make_unique<WriteUnitTestingStructAttr>(), //
        make_unique<SubscribeAttributeUnitTestingStructAttr>(), //
        make_unique<ReadUnitTestingRangeRestrictedInt8u>(), //
        make_unique<WriteUnitTestingRangeRestrictedInt8u>(), //
        make_unique<SubscribeAttributeUnitTestingRangeRestrictedInt8u>(), //
        make_unique<ReadUnitTestingRangeRestrictedInt8s>(), //
        make_unique<WriteUnitTestingRangeRestrictedInt8s>(), //
        make_unique<SubscribeAttributeUnitTestingRangeRestrictedInt8s>(), //
        make_unique<ReadUnitTestingRangeRestrictedInt16u>(), //
        make_unique<WriteUnitTestingRangeRestrictedInt16u>(), //
        make_unique<SubscribeAttributeUnitTestingRangeRestrictedInt16u>(), //
        make_unique<ReadUnitTestingRangeRestrictedInt16s>(), //
        make_unique<WriteUnitTestingRangeRestrictedInt16s>(), //
        make_unique<SubscribeAttributeUnitTestingRangeRestrictedInt16s>(), //
        make_unique<ReadUnitTestingListLongOctetString>(), //
        make_unique<WriteUnitTestingListLongOctetString>(), //
        make_unique<SubscribeAttributeUnitTestingListLongOctetString>(), //
        make_unique<ReadUnitTestingListFabricScoped>(), //
        make_unique<WriteUnitTestingListFabricScoped>(), //
        make_unique<SubscribeAttributeUnitTestingListFabricScoped>(), //
        make_unique<ReadUnitTestingTimedWriteBoolean>(), //
        make_unique<WriteUnitTestingTimedWriteBoolean>(), //
        make_unique<SubscribeAttributeUnitTestingTimedWriteBoolean>(), //
        make_unique<ReadUnitTestingGeneralErrorBoolean>(), //
        make_unique<WriteUnitTestingGeneralErrorBoolean>(), //
        make_unique<SubscribeAttributeUnitTestingGeneralErrorBoolean>(), //
        make_unique<ReadUnitTestingClusterErrorBoolean>(), //
        make_unique<WriteUnitTestingClusterErrorBoolean>(), //
        make_unique<SubscribeAttributeUnitTestingClusterErrorBoolean>(), //
        make_unique<ReadUnitTestingUnsupported>(), //
        make_unique<WriteUnitTestingUnsupported>(), //
        make_unique<SubscribeAttributeUnitTestingUnsupported>(), //
        make_unique<ReadUnitTestingNullableBoolean>(), //
        make_unique<WriteUnitTestingNullableBoolean>(), //
        make_unique<SubscribeAttributeUnitTestingNullableBoolean>(), //
        make_unique<ReadUnitTestingNullableBitmap8>(), //
        make_unique<WriteUnitTestingNullableBitmap8>(), //
        make_unique<SubscribeAttributeUnitTestingNullableBitmap8>(), //
        make_unique<ReadUnitTestingNullableBitmap16>(), //
        make_unique<WriteUnitTestingNullableBitmap16>(), //
        make_unique<SubscribeAttributeUnitTestingNullableBitmap16>(), //
        make_unique<ReadUnitTestingNullableBitmap32>(), //
        make_unique<WriteUnitTestingNullableBitmap32>(), //
        make_unique<SubscribeAttributeUnitTestingNullableBitmap32>(), //
        make_unique<ReadUnitTestingNullableBitmap64>(), //
        make_unique<WriteUnitTestingNullableBitmap64>(), //
        make_unique<SubscribeAttributeUnitTestingNullableBitmap64>(), //
        make_unique<ReadUnitTestingNullableInt8u>(), //
        make_unique<WriteUnitTestingNullableInt8u>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt8u>(), //
        make_unique<ReadUnitTestingNullableInt16u>(), //
        make_unique<WriteUnitTestingNullableInt16u>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt16u>(), //
        make_unique<ReadUnitTestingNullableInt24u>(), //
        make_unique<WriteUnitTestingNullableInt24u>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt24u>(), //
        make_unique<ReadUnitTestingNullableInt32u>(), //
        make_unique<WriteUnitTestingNullableInt32u>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt32u>(), //
        make_unique<ReadUnitTestingNullableInt40u>(), //
        make_unique<WriteUnitTestingNullableInt40u>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt40u>(), //
        make_unique<ReadUnitTestingNullableInt48u>(), //
        make_unique<WriteUnitTestingNullableInt48u>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt48u>(), //
        make_unique<ReadUnitTestingNullableInt56u>(), //
        make_unique<WriteUnitTestingNullableInt56u>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt56u>(), //
        make_unique<ReadUnitTestingNullableInt64u>(), //
        make_unique<WriteUnitTestingNullableInt64u>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt64u>(), //
        make_unique<ReadUnitTestingNullableInt8s>(), //
        make_unique<WriteUnitTestingNullableInt8s>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt8s>(), //
        make_unique<ReadUnitTestingNullableInt16s>(), //
        make_unique<WriteUnitTestingNullableInt16s>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt16s>(), //
        make_unique<ReadUnitTestingNullableInt24s>(), //
        make_unique<WriteUnitTestingNullableInt24s>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt24s>(), //
        make_unique<ReadUnitTestingNullableInt32s>(), //
        make_unique<WriteUnitTestingNullableInt32s>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt32s>(), //
        make_unique<ReadUnitTestingNullableInt40s>(), //
        make_unique<WriteUnitTestingNullableInt40s>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt40s>(), //
        make_unique<ReadUnitTestingNullableInt48s>(), //
        make_unique<WriteUnitTestingNullableInt48s>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt48s>(), //
        make_unique<ReadUnitTestingNullableInt56s>(), //
        make_unique<WriteUnitTestingNullableInt56s>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt56s>(), //
        make_unique<ReadUnitTestingNullableInt64s>(), //
        make_unique<WriteUnitTestingNullableInt64s>(), //
        make_unique<SubscribeAttributeUnitTestingNullableInt64s>(), //
        make_unique<ReadUnitTestingNullableEnum8>(), //
        make_unique<WriteUnitTestingNullableEnum8>(), //
        make_unique<SubscribeAttributeUnitTestingNullableEnum8>(), //
        make_unique<ReadUnitTestingNullableEnum16>(), //
        make_unique<WriteUnitTestingNullableEnum16>(), //
        make_unique<SubscribeAttributeUnitTestingNullableEnum16>(), //
        make_unique<ReadUnitTestingNullableFloatSingle>(), //
        make_unique<WriteUnitTestingNullableFloatSingle>(), //
        make_unique<SubscribeAttributeUnitTestingNullableFloatSingle>(), //
        make_unique<ReadUnitTestingNullableFloatDouble>(), //
        make_unique<WriteUnitTestingNullableFloatDouble>(), //
        make_unique<SubscribeAttributeUnitTestingNullableFloatDouble>(), //
        make_unique<ReadUnitTestingNullableOctetString>(), //
        make_unique<WriteUnitTestingNullableOctetString>(), //
        make_unique<SubscribeAttributeUnitTestingNullableOctetString>(), //
        make_unique<ReadUnitTestingNullableCharString>(), //
        make_unique<WriteUnitTestingNullableCharString>(), //
        make_unique<SubscribeAttributeUnitTestingNullableCharString>(), //
        make_unique<ReadUnitTestingNullableEnumAttr>(), //
        make_unique<WriteUnitTestingNullableEnumAttr>(), //
        make_unique<SubscribeAttributeUnitTestingNullableEnumAttr>(), //
        make_unique<ReadUnitTestingNullableStruct>(), //
        make_unique<WriteUnitTestingNullableStruct>(), //
        make_unique<SubscribeAttributeUnitTestingNullableStruct>(), //
        make_unique<ReadUnitTestingNullableRangeRestrictedInt8u>(), //
        make_unique<WriteUnitTestingNullableRangeRestrictedInt8u>(), //
        make_unique<SubscribeAttributeUnitTestingNullableRangeRestrictedInt8u>(), //
        make_unique<ReadUnitTestingNullableRangeRestrictedInt8s>(), //
        make_unique<WriteUnitTestingNullableRangeRestrictedInt8s>(), //
        make_unique<SubscribeAttributeUnitTestingNullableRangeRestrictedInt8s>(), //
        make_unique<ReadUnitTestingNullableRangeRestrictedInt16u>(), //
        make_unique<WriteUnitTestingNullableRangeRestrictedInt16u>(), //
        make_unique<SubscribeAttributeUnitTestingNullableRangeRestrictedInt16u>(), //
        make_unique<ReadUnitTestingNullableRangeRestrictedInt16s>(), //
        make_unique<WriteUnitTestingNullableRangeRestrictedInt16s>(), //
        make_unique<SubscribeAttributeUnitTestingNullableRangeRestrictedInt16s>(), //
        make_unique<ReadUnitTestingWriteOnlyInt8u>(), //
        make_unique<WriteUnitTestingWriteOnlyInt8u>(), //
        make_unique<SubscribeAttributeUnitTestingWriteOnlyInt8u>(), //
        make_unique<ReadUnitTestingGeneratedCommandList>(), //
        make_unique<SubscribeAttributeUnitTestingGeneratedCommandList>(), //
        make_unique<ReadUnitTestingAcceptedCommandList>(), //
        make_unique<SubscribeAttributeUnitTestingAcceptedCommandList>(), //
        make_unique<ReadUnitTestingEventList>(), //
        make_unique<SubscribeAttributeUnitTestingEventList>(), //
        make_unique<ReadUnitTestingAttributeList>(), //
        make_unique<SubscribeAttributeUnitTestingAttributeList>(), //
        make_unique<ReadUnitTestingFeatureMap>(), //
        make_unique<SubscribeAttributeUnitTestingFeatureMap>(), //
        make_unique<ReadUnitTestingClusterRevision>(), //
        make_unique<SubscribeAttributeUnitTestingClusterRevision>(), //
        make_unique<ReadEvent>(Id), //
        make_unique<SubscribeEvent>(Id), //
    };

    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<ReadEvent>(), //
        make_unique<SubscribeEvent>(chip::kInvalidClusterId, true), //
        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);
    registerClusterBasicInformation(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);
    registerClusterBridgedDeviceBasicInformation(commands);
    registerClusterSwitch(commands);
    registerClusterAdministratorCommissioning(commands);
    registerClusterOperationalCredentials(commands);
    registerClusterGroupKeyManagement(commands);
    registerClusterFixedLabel(commands);
    registerClusterUserLabel(commands);
    registerClusterBooleanState(commands);
    registerClusterModeSelect(commands);
    registerClusterTemperatureControl(commands);
    registerClusterRefrigeratorAlarm(commands);
    registerClusterAirQuality(commands);
    registerClusterSmokeCoAlarm(commands);
    registerClusterHepaFilterMonitoring(commands);
    registerClusterActivatedCarbonFilterMonitoring(commands);
    registerClusterCeramicFilterMonitoring(commands);
    registerClusterElectrostaticFilterMonitoring(commands);
    registerClusterUvFilterMonitoring(commands);
    registerClusterIonizingFilterMonitoring(commands);
    registerClusterZeoliteFilterMonitoring(commands);
    registerClusterOzoneFilterMonitoring(commands);
    registerClusterWaterTankMonitoring(commands);
    registerClusterFuelTankMonitoring(commands);
    registerClusterInkCartridgeMonitoring(commands);
    registerClusterTonerCartridgeMonitoring(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);
    registerClusterUnitTesting(commands);
}
