/*
 *
 *    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 |
| BridgedActions                                                      | 0x0025 |
| Basic                                                               | 0x0028 |
| OtaSoftwareUpdateProvider                                           | 0x0029 |
| OtaSoftwareUpdateRequestor                                          | 0x002A |
| LocalizationConfiguration                                           | 0x002B |
| TimeFormatLocalization                                              | 0x002C |
| UnitLocalization                                                    | 0x002D |
| PowerSourceConfiguration                                            | 0x002E |
| PowerSource                                                         | 0x002F |
| GeneralCommissioning                                                | 0x0030 |
| NetworkCommissioning                                                | 0x0031 |
| DiagnosticLogs                                                      | 0x0032 |
| GeneralDiagnostics                                                  | 0x0033 |
| SoftwareDiagnostics                                                 | 0x0034 |
| ThreadNetworkDiagnostics                                            | 0x0035 |
| WiFiNetworkDiagnostics                                              | 0x0036 |
| EthernetNetworkDiagnostics                                          | 0x0037 |
| TimeSynchronization                                                 | 0x0038 |
| BridgedDeviceBasic                                                  | 0x0039 |
| Switch                                                              | 0x003B |
| AdministratorCommissioning                                          | 0x003C |
| OperationalCredentials                                              | 0x003E |
| GroupKeyManagement                                                  | 0x003F |
| FixedLabel                                                          | 0x0040 |
| UserLabel                                                           | 0x0041 |
| ProxyConfiguration                                                  | 0x0042 |
| ProxyDiscovery                                                      | 0x0043 |
| ProxyValid                                                          | 0x0044 |
| BooleanState                                                        | 0x0045 |
| ModeSelect                                                          | 0x0050 |
| DoorLock                                                            | 0x0101 |
| WindowCovering                                                      | 0x0102 |
| BarrierControl                                                      | 0x0103 |
| PumpConfigurationAndControl                                         | 0x0200 |
| Thermostat                                                          | 0x0201 |
| FanControl                                                          | 0x0202 |
| ThermostatUserInterfaceConfiguration                                | 0x0204 |
| ColorControl                                                        | 0x0300 |
| BallastConfiguration                                                | 0x0301 |
| IlluminanceMeasurement                                              | 0x0400 |
| TemperatureMeasurement                                              | 0x0402 |
| PressureMeasurement                                                 | 0x0403 |
| FlowMeasurement                                                     | 0x0404 |
| RelativeHumidityMeasurement                                         | 0x0405 |
| OccupancySensing                                                    | 0x0406 |
| WakeOnLan                                                           | 0x0503 |
| Channel                                                             | 0x0504 |
| TargetNavigator                                                     | 0x0505 |
| MediaPlayback                                                       | 0x0506 |
| MediaInput                                                          | 0x0507 |
| LowPower                                                            | 0x0508 |
| KeypadInput                                                         | 0x0509 |
| ContentLauncher                                                     | 0x050A |
| AudioOutput                                                         | 0x050B |
| ApplicationLauncher                                                 | 0x050C |
| ApplicationBasic                                                    | 0x050D |
| AccountLogin                                                        | 0x050E |
| ElectricalMeasurement                                               | 0x0B04 |
| TestCluster                                                         | 0xFFF1FC05|
\*----------------------------------------------------------------------------*/

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                                 endpoint: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
                      completionHandler:^(NSError * _Nullable error) {
                          responsesNeeded--;
                          if (error != nil) {
                              mError = error;
                              LogNSError("Error", error);
                          }
                          if (responsesNeeded == 0) {
                              SetCommandExitStatus(mError);
                          }
                      }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                                 endpoint: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
                           completionHandler:^(NSError * _Nullable error) {
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

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

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

    ~ReadIdentifyIdentifyTime() {}

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

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

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

    ~WriteIdentifyIdentifyTime() {}

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

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

private:
    uint16_t mValue;
};

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

    ~SubscribeAttributeIdentifyIdentifyTime() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIdentifyIdentifyType() {}

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

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

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

    ~SubscribeAttributeIdentifyIdentifyType() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIdentifyGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeIdentifyGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIdentifyAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeIdentifyAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIdentifyAttributeList() {}

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

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

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

    ~SubscribeAttributeIdentifyAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIdentifyFeatureMap() {}

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

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

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

    ~SubscribeAttributeIdentifyFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadIdentifyClusterRevision() {}

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

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

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

    ~SubscribeAttributeIdentifyClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                             endpoint: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
                      completionHandler:^(MTRGroupsClusterAddGroupResponseParams * _Nullable values, NSError * _Nullable error) {
                          NSLog(@"Values: %@", values);
                          responsesNeeded--;
                          if (error != nil) {
                              mError = error;
                              LogNSError("Error", error);
                          }
                          if (responsesNeeded == 0) {
                              SetCommandExitStatus(mError);
                          }
                      }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                             endpoint: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
                       completionHandler:^(MTRGroupsClusterViewGroupResponseParams * _Nullable values, NSError * _Nullable error) {
                           NSLog(@"Values: %@", values);
                           responsesNeeded--;
                           if (error != nil) {
                               mError = error;
                               LogNSError("Error", error);
                           }
                           if (responsesNeeded == 0) {
                               SetCommandExitStatus(mError);
                           }
                       }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                             endpoint: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
                                completionHandler:^(MTRGroupsClusterGetGroupMembershipResponseParams * _Nullable values,
                                    NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                             endpoint: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
                    completionHandler:^(MTRGroupsClusterRemoveGroupResponseParams * _Nullable values, NSError * _Nullable error) {
                        NSLog(@"Values: %@", values);
                        responsesNeeded--;
                        if (error != nil) {
                            mError = error;
                            LogNSError("Error", error);
                        }
                        if (responsesNeeded == 0) {
                            SetCommandExitStatus(mError);
                        }
                    }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                             endpoint: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
                             completionHandler:^(NSError * _Nullable error) {
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                             endpoint: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
                                   completionHandler:^(NSError * _Nullable error) {
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

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

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

    ~ReadGroupsNameSupport() {}

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

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

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

    ~SubscribeAttributeGroupsNameSupport() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadGroupsGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeGroupsGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadGroupsAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeGroupsAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadGroupsAttributeList() {}

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

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

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

    ~SubscribeAttributeGroupsAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadGroupsFeatureMap() {}

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

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

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

    ~SubscribeAttributeGroupsFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadGroupsClusterRevision() {}

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

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

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

    ~SubscribeAttributeGroupsClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                             endpoint: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
                      completionHandler:^(MTRScenesClusterAddSceneResponseParams * _Nullable values, NSError * _Nullable error) {
                          NSLog(@"Values: %@", values);
                          responsesNeeded--;
                          if (error != nil) {
                              mError = error;
                              LogNSError("Error", error);
                          }
                          if (responsesNeeded == 0) {
                              SetCommandExitStatus(mError);
                          }
                      }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                             endpoint: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
                       completionHandler:^(MTRScenesClusterViewSceneResponseParams * _Nullable values, NSError * _Nullable error) {
                           NSLog(@"Values: %@", values);
                           responsesNeeded--;
                           if (error != nil) {
                               mError = error;
                               LogNSError("Error", error);
                           }
                           if (responsesNeeded == 0) {
                               SetCommandExitStatus(mError);
                           }
                       }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                             endpoint: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
                    completionHandler:^(MTRScenesClusterRemoveSceneResponseParams * _Nullable values, NSError * _Nullable error) {
                        NSLog(@"Values: %@", values);
                        responsesNeeded--;
                        if (error != nil) {
                            mError = error;
                            LogNSError("Error", error);
                        }
                        if (responsesNeeded == 0) {
                            SetCommandExitStatus(mError);
                        }
                    }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                             endpoint: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
                             completionHandler:^(
                                 MTRScenesClusterRemoveAllScenesResponseParams * _Nullable values, NSError * _Nullable error) {
                                 NSLog(@"Values: %@", values);
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                             endpoint: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
                   completionHandler:^(MTRScenesClusterStoreSceneResponseParams * _Nullable values, NSError * _Nullable error) {
                       NSLog(@"Values: %@", values);
                       responsesNeeded--;
                       if (error != nil) {
                           mError = error;
                           LogNSError("Error", error);
                       }
                       if (responsesNeeded == 0) {
                           SetCommandExitStatus(mError);
                       }
                   }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                             endpoint: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
                         completionHandler:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                             endpoint: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
                                completionHandler:^(MTRScenesClusterGetSceneMembershipResponseParams * _Nullable values,
                                    NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                             endpoint: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
                              completionHandler:^(
                                  MTRScenesClusterEnhancedAddSceneResponseParams * _Nullable values, NSError * _Nullable error) {
                                  NSLog(@"Values: %@", values);
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                             endpoint: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
                               completionHandler:^(
                                   MTRScenesClusterEnhancedViewSceneResponseParams * _Nullable values, NSError * _Nullable error) {
                                   NSLog(@"Values: %@", values);
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

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

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

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

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

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

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

    ~ReadScenesSceneCount() {}

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

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

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

    ~SubscribeAttributeScenesSceneCount() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadScenesCurrentScene() {}

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

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

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

    ~SubscribeAttributeScenesCurrentScene() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadScenesCurrentGroup() {}

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

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

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

    ~SubscribeAttributeScenesCurrentGroup() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadScenesSceneValid() {}

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

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

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

    ~SubscribeAttributeScenesSceneValid() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadScenesNameSupport() {}

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

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

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

    ~SubscribeAttributeScenesNameSupport() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadScenesLastConfiguredBy() {}

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

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

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

    ~SubscribeAttributeScenesLastConfiguredBy() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadScenesGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeScenesGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadScenesAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeScenesAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadScenesAttributeList() {}

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

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

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

    ~SubscribeAttributeScenesAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadScenesFeatureMap() {}

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

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

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

    ~SubscribeAttributeScenesFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadScenesClusterRevision() {}

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

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

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

    ~SubscribeAttributeScenesClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint: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
                 completionHandler:^(NSError * _Nullable error) {
                     responsesNeeded--;
                     if (error != nil) {
                         mError = error;
                         LogNSError("Error", error);
                     }
                     if (responsesNeeded == 0) {
                         SetCommandExitStatus(mError);
                     }
                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint: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
                completionHandler:^(NSError * _Nullable error) {
                    responsesNeeded--;
                    if (error != nil) {
                        mError = error;
                        LogNSError("Error", error);
                    }
                    if (responsesNeeded == 0) {
                        SetCommandExitStatus(mError);
                    }
                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint: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
                    completionHandler:^(NSError * _Nullable error) {
                        responsesNeeded--;
                        if (error != nil) {
                            mError = error;
                            LogNSError("Error", error);
                        }
                        if (responsesNeeded == 0) {
                            SetCommandExitStatus(mError);
                        }
                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

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

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

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

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint: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
                                     completionHandler:^(NSError * _Nullable error) {
                                         responsesNeeded--;
                                         if (error != nil) {
                                             mError = error;
                                             LogNSError("Error", error);
                                         }
                                         if (responsesNeeded == 0) {
                                             SetCommandExitStatus(mError);
                                         }
                                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device endpoint: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
                            completionHandler:^(NSError * _Nullable error) {
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

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

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

    ~ReadOnOffOnOff() {}

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

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

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

    ~SubscribeAttributeOnOffOnOff() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffGlobalSceneControl() {}

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

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

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

    ~SubscribeAttributeOnOffGlobalSceneControl() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffOnTime() {}

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

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

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

    ~WriteOnOffOnTime() {}

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

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

private:
    uint16_t mValue;
};

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

    ~SubscribeAttributeOnOffOnTime() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffOffWaitTime() {}

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

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

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

    ~WriteOnOffOffWaitTime() {}

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

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

private:
    uint16_t mValue;
};

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

    ~SubscribeAttributeOnOffOffWaitTime() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffStartUpOnOff() {}

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

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

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

    ~WriteOnOffStartUpOnOff() {}

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

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

private:
    uint8_t mValue;
};

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

    ~SubscribeAttributeOnOffStartUpOnOff() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeOnOffGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeOnOffAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffAttributeList() {}

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

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

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

    ~SubscribeAttributeOnOffAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffFeatureMap() {}

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

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

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

    ~SubscribeAttributeOnOffFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffClusterRevision() {}

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

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

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

    ~SubscribeAttributeOnOffClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

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

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

    ~ReadOnOffSwitchConfigurationSwitchType() {}

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

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

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

    ~SubscribeAttributeOnOffSwitchConfigurationSwitchType() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffSwitchConfigurationSwitchActions() {}

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

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

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

    ~WriteOnOffSwitchConfigurationSwitchActions() {}

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

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

private:
    uint8_t mValue;
};

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

    ~SubscribeAttributeOnOffSwitchConfigurationSwitchActions() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffSwitchConfigurationGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeOnOffSwitchConfigurationGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffSwitchConfigurationAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeOnOffSwitchConfigurationAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffSwitchConfigurationAttributeList() {}

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

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

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

    ~SubscribeAttributeOnOffSwitchConfigurationAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffSwitchConfigurationFeatureMap() {}

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

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

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

    ~SubscribeAttributeOnOffSwitchConfigurationFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadOnOffSwitchConfigurationClusterRevision() {}

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

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

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

    ~SubscribeAttributeOnOffSwitchConfigurationClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                         endpoint: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
                                    completionHandler:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

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

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

    ~ReadLevelControlCurrentLevel() {}

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

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

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

    ~SubscribeAttributeLevelControlCurrentLevel() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlRemainingTime() {}

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

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

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

    ~SubscribeAttributeLevelControlRemainingTime() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlMinLevel() {}

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

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

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

    ~SubscribeAttributeLevelControlMinLevel() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlMaxLevel() {}

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

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

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

    ~SubscribeAttributeLevelControlMaxLevel() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlCurrentFrequency() {}

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

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

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

    ~SubscribeAttributeLevelControlCurrentFrequency() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlMinFrequency() {}

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

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

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

    ~SubscribeAttributeLevelControlMinFrequency() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlMaxFrequency() {}

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

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

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

    ~SubscribeAttributeLevelControlMaxFrequency() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlOptions() {}

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

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

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

    ~WriteLevelControlOptions() {}

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

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

private:
    uint8_t mValue;
};

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

    ~SubscribeAttributeLevelControlOptions() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlOnOffTransitionTime() {}

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

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

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

    ~WriteLevelControlOnOffTransitionTime() {}

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

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

private:
    uint16_t mValue;
};

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

    ~SubscribeAttributeLevelControlOnOffTransitionTime() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlOnLevel() {}

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

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

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

    ~WriteLevelControlOnLevel() {}

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

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

private:
    uint8_t mValue;
};

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

    ~SubscribeAttributeLevelControlOnLevel() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlOnTransitionTime() {}

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

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

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

    ~WriteLevelControlOnTransitionTime() {}

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

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

private:
    uint16_t mValue;
};

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

    ~SubscribeAttributeLevelControlOnTransitionTime() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlOffTransitionTime() {}

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

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

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

    ~WriteLevelControlOffTransitionTime() {}

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

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

private:
    uint16_t mValue;
};

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

    ~SubscribeAttributeLevelControlOffTransitionTime() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlDefaultMoveRate() {}

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

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

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

    ~WriteLevelControlDefaultMoveRate() {}

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

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

private:
    uint8_t mValue;
};

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

    ~SubscribeAttributeLevelControlDefaultMoveRate() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlStartUpCurrentLevel() {}

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

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

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

    ~WriteLevelControlStartUpCurrentLevel() {}

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

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

private:
    uint8_t mValue;
};

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

    ~SubscribeAttributeLevelControlStartUpCurrentLevel() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeLevelControlGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeLevelControlAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlAttributeList() {}

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

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

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

    ~SubscribeAttributeLevelControlAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlFeatureMap() {}

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

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

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

    ~SubscribeAttributeLevelControlFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadLevelControlClusterRevision() {}

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

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

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

    ~SubscribeAttributeLevelControlClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

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

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

    ~ReadBinaryInputBasicActiveText() {}

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

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

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

    ~WriteBinaryInputBasicActiveText() {}

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

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

private:
    chip::ByteSpan mValue;
};

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

    ~SubscribeAttributeBinaryInputBasicActiveText() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicDescription() {}

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

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

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

    ~WriteBinaryInputBasicDescription() {}

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

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

private:
    chip::ByteSpan mValue;
};

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

    ~SubscribeAttributeBinaryInputBasicDescription() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicInactiveText() {}

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

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

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

    ~WriteBinaryInputBasicInactiveText() {}

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

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

private:
    chip::ByteSpan mValue;
};

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

    ~SubscribeAttributeBinaryInputBasicInactiveText() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicOutOfService() {}

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

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

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

    ~WriteBinaryInputBasicOutOfService() {}

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

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

private:
    bool mValue;
};

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

    ~SubscribeAttributeBinaryInputBasicOutOfService() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicPolarity() {}

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

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

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

    ~SubscribeAttributeBinaryInputBasicPolarity() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicPresentValue() {}

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

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

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

    ~WriteBinaryInputBasicPresentValue() {}

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

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

private:
    bool mValue;
};

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

    ~SubscribeAttributeBinaryInputBasicPresentValue() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicReliability() {}

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

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

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

    ~WriteBinaryInputBasicReliability() {}

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

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

private:
    uint8_t mValue;
};

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

    ~SubscribeAttributeBinaryInputBasicReliability() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicStatusFlags() {}

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

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

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

    ~SubscribeAttributeBinaryInputBasicStatusFlags() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicApplicationType() {}

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

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

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

    ~SubscribeAttributeBinaryInputBasicApplicationType() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeBinaryInputBasicGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeBinaryInputBasicAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicAttributeList() {}

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

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

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

    ~SubscribeAttributeBinaryInputBasicAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicFeatureMap() {}

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

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

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

    ~SubscribeAttributeBinaryInputBasicFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBinaryInputBasicClusterRevision() {}

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

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

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

    ~SubscribeAttributeBinaryInputBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params: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:                                                         |        |
| * DeviceList                                                        | 0x0000 |
| * ServerList                                                        | 0x0001 |
| * ClientList                                                        | 0x0002 |
| * PartsList                                                         | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute DeviceList
 */
class ReadDescriptorDeviceList : public ReadAttribute {
public:
    ReadDescriptorDeviceList()
        : ReadAttribute("device-list")
    {
    }

    ~ReadDescriptorDeviceList() {}

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

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

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

    ~SubscribeAttributeDescriptorDeviceList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDeviceListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.DeviceList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadDescriptorServerList() {}

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

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

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

    ~SubscribeAttributeDescriptorServerList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadDescriptorClientList() {}

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

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

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

    ~SubscribeAttributeDescriptorClientList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadDescriptorPartsList() {}

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

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

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

    ~SubscribeAttributeDescriptorPartsList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadDescriptorGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeDescriptorGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadDescriptorAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeDescriptorAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadDescriptorAttributeList() {}

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

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

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

    ~SubscribeAttributeDescriptorAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadDescriptorFeatureMap() {}

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

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

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

    ~SubscribeAttributeDescriptorFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadDescriptorClusterRevision() {}

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

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

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

    ~SubscribeAttributeDescriptorClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

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

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

    ~ReadBindingBinding() {}

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

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

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

    ~WriteBindingBinding() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRBindingClusterTargetStruct * newElement_0;
                newElement_0 = [MTRBindingClusterTargetStruct new];
                if (entry_0.node.HasValue()) {
                    newElement_0.node = [NSNumber numberWithUnsignedLongLong:entry_0.node.Value()];
                } else {
                    newElement_0.node = nil;
                }
                if (entry_0.group.HasValue()) {
                    newElement_0.group = [NSNumber numberWithUnsignedShort:entry_0.group.Value()];
                } else {
                    newElement_0.group = nil;
                }
                if (entry_0.endpoint.HasValue()) {
                    newElement_0.endpoint = [NSNumber numberWithUnsignedShort:entry_0.endpoint.Value()];
                } else {
                    newElement_0.endpoint = nil;
                }
                if (entry_0.cluster.HasValue()) {
                    newElement_0.cluster = [NSNumber numberWithUnsignedInt:entry_0.cluster.Value()];
                } else {
                    newElement_0.cluster = nil;
                }
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

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

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

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

    ~SubscribeAttributeBindingBinding() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBindingGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeBindingGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBindingAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeBindingAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBindingAttributeList() {}

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

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

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

    ~SubscribeAttributeBindingAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBindingFeatureMap() {}

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

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

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

    ~SubscribeAttributeBindingFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBindingClusterRevision() {}

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

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

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

    ~SubscribeAttributeBindingClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

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

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

    ~ReadAccessControlAcl() {}

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

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

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

    ~WriteAccessControlAcl() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRAccessControlClusterAccessControlEntry * newElement_0;
                newElement_0 = [MTRAccessControlClusterAccessControlEntry new];
                newElement_0.privilege = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.privilege)];
                newElement_0.authMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.authMode)];
                if (entry_0.subjects.IsNull()) {
                    newElement_0.subjects = nil;
                } else {
                    { // Scope for our temporary variables
                        auto * array_3 = [NSMutableArray new];
                        for (auto & entry_3 : entry_0.subjects.Value()) {
                            NSNumber * newElement_3;
                            newElement_3 = [NSNumber numberWithUnsignedLongLong:entry_3];
                            [array_3 addObject:newElement_3];
                        }
                        newElement_0.subjects = array_3;
                    }
                }
                if (entry_0.targets.IsNull()) {
                    newElement_0.targets = nil;
                } else {
                    { // Scope for our temporary variables
                        auto * array_3 = [NSMutableArray new];
                        for (auto & entry_3 : entry_0.targets.Value()) {
                            MTRAccessControlClusterTarget * newElement_3;
                            newElement_3 = [MTRAccessControlClusterTarget new];
                            if (entry_3.cluster.IsNull()) {
                                newElement_3.cluster = nil;
                            } else {
                                newElement_3.cluster = [NSNumber numberWithUnsignedInt:entry_3.cluster.Value()];
                            }
                            if (entry_3.endpoint.IsNull()) {
                                newElement_3.endpoint = nil;
                            } else {
                                newElement_3.endpoint = [NSNumber numberWithUnsignedShort:entry_3.endpoint.Value()];
                            }
                            if (entry_3.deviceType.IsNull()) {
                                newElement_3.deviceType = nil;
                            } else {
                                newElement_3.deviceType = [NSNumber numberWithUnsignedInt:entry_3.deviceType.Value()];
                            }
                            [array_3 addObject:newElement_3];
                        }
                        newElement_0.targets = array_3;
                    }
                }
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

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

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

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

    ~SubscribeAttributeAccessControlAcl() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAccessControlExtension() {}

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

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

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

    ~WriteAccessControlExtension() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRAccessControlClusterExtensionEntry * newElement_0;
                newElement_0 = [MTRAccessControlClusterExtensionEntry new];
                newElement_0.data = [NSData dataWithBytes:entry_0.data.data() length:entry_0.data.size()];
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

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

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

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

    ~SubscribeAttributeAccessControlExtension() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAccessControlSubjectsPerAccessControlEntry() {}

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

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

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

    ~SubscribeAttributeAccessControlSubjectsPerAccessControlEntry() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAccessControlTargetsPerAccessControlEntry() {}

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

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

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

    ~SubscribeAttributeAccessControlTargetsPerAccessControlEntry() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAccessControlAccessControlEntriesPerFabric() {}

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

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

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

    ~SubscribeAttributeAccessControlAccessControlEntriesPerFabric() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAccessControlGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeAccessControlGeneratedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAccessControlAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeAccessControlAcceptedCommandList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAccessControlAttributeList() {}

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

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

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

    ~SubscribeAttributeAccessControlAttributeList() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAccessControlFeatureMap() {}

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

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

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

    ~SubscribeAttributeAccessControlFeatureMap() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadAccessControlClusterRevision() {}

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

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

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

    ~SubscribeAttributeAccessControlClusterRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster BridgedActions                                              | 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 |
| * EndpointList                                                      | 0x0001 |
| * SetupUrl                                                          | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StateChanged                                                      | 0x0000 |
| * ActionFailed                                                      | 0x0001 |
\*----------------------------------------------------------------------------*/

/*
 * Command InstantAction
 */
class BridgedActionsInstantAction : public ClusterCommand {
public:
    BridgedActionsInstantAction()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterInstantActionParams 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
                           completionHandler:^(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::BridgedActions::Commands::InstantAction::Type mRequest;
};

/*
 * Command InstantActionWithTransition
 */
class BridgedActionsInstantActionWithTransition : public ClusterCommand {
public:
    BridgedActionsInstantActionWithTransition()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterInstantActionWithTransitionParams 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
                                         completionHandler:^(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::BridgedActions::Commands::InstantActionWithTransition::Type mRequest;
};

/*
 * Command StartAction
 */
class BridgedActionsStartAction : public ClusterCommand {
public:
    BridgedActionsStartAction()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterStartActionParams 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
                         completionHandler:^(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::BridgedActions::Commands::StartAction::Type mRequest;
};

/*
 * Command StartActionWithDuration
 */
class BridgedActionsStartActionWithDuration : public ClusterCommand {
public:
    BridgedActionsStartActionWithDuration()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterStartActionWithDurationParams 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
                                     completionHandler:^(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::BridgedActions::Commands::StartActionWithDuration::Type mRequest;
};

/*
 * Command StopAction
 */
class BridgedActionsStopAction : public ClusterCommand {
public:
    BridgedActionsStopAction()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterStopActionParams 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
                        completionHandler:^(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::BridgedActions::Commands::StopAction::Type mRequest;
};

/*
 * Command PauseAction
 */
class BridgedActionsPauseAction : public ClusterCommand {
public:
    BridgedActionsPauseAction()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterPauseActionParams 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
                         completionHandler:^(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::BridgedActions::Commands::PauseAction::Type mRequest;
};

/*
 * Command PauseActionWithDuration
 */
class BridgedActionsPauseActionWithDuration : public ClusterCommand {
public:
    BridgedActionsPauseActionWithDuration()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterPauseActionWithDurationParams 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
                                     completionHandler:^(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::BridgedActions::Commands::PauseActionWithDuration::Type mRequest;
};

/*
 * Command ResumeAction
 */
class BridgedActionsResumeAction : public ClusterCommand {
public:
    BridgedActionsResumeAction()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterResumeActionParams 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
                          completionHandler:^(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::BridgedActions::Commands::ResumeAction::Type mRequest;
};

/*
 * Command EnableAction
 */
class BridgedActionsEnableAction : public ClusterCommand {
public:
    BridgedActionsEnableAction()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterEnableActionParams 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
                          completionHandler:^(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::BridgedActions::Commands::EnableAction::Type mRequest;
};

/*
 * Command EnableActionWithDuration
 */
class BridgedActionsEnableActionWithDuration : public ClusterCommand {
public:
    BridgedActionsEnableActionWithDuration()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterEnableActionWithDurationParams 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
                                      completionHandler:^(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::BridgedActions::Commands::EnableActionWithDuration::Type mRequest;
};

/*
 * Command DisableAction
 */
class BridgedActionsDisableAction : public ClusterCommand {
public:
    BridgedActionsDisableAction()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterDisableActionParams 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
                           completionHandler:^(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::BridgedActions::Commands::DisableAction::Type mRequest;
};

/*
 * Command DisableActionWithDuration
 */
class BridgedActionsDisableActionWithDuration : public ClusterCommand {
public:
    BridgedActionsDisableActionWithDuration()
        : 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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBridgedActionsClusterDisableActionWithDurationParams 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
                                       completionHandler:^(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::BridgedActions::Commands::DisableActionWithDuration::Type mRequest;
};

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

    ~ReadBridgedActionsActionList() {}

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

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

    ~SubscribeAttributeBridgedActionsActionList() {}

    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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActionListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedActions.ActionList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EndpointList
 */
class ReadBridgedActionsEndpointList : public ReadAttribute {
public:
    ReadBridgedActionsEndpointList()
        : ReadAttribute("endpoint-list")
    {
    }

    ~ReadBridgedActionsEndpointList() {}

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

class SubscribeAttributeBridgedActionsEndpointList : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedActionsEndpointList()
        : SubscribeAttribute("endpoint-list")
    {
    }

    ~SubscribeAttributeBridgedActionsEndpointList() {}

    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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEndpointListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedActions.EndpointList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SetupUrl
 */
class ReadBridgedActionsSetupUrl : public ReadAttribute {
public:
    ReadBridgedActionsSetupUrl()
        : ReadAttribute("setup-url")
    {
    }

    ~ReadBridgedActionsSetupUrl() {}

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

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

    ~SubscribeAttributeBridgedActionsSetupUrl() {}

    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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSetupUrlWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedActions.SetupUrl response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBridgedActionsGeneratedCommandList() {}

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

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

    ~SubscribeAttributeBridgedActionsGeneratedCommandList() {}

    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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedActions.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBridgedActionsAcceptedCommandList() {}

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

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

    ~SubscribeAttributeBridgedActionsAcceptedCommandList() {}

    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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedActions.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBridgedActionsAttributeList() {}

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

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

    ~SubscribeAttributeBridgedActionsAttributeList() {}

    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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedActions.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBridgedActionsFeatureMap() {}

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

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

    ~SubscribeAttributeBridgedActionsFeatureMap() {}

    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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedActions.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBridgedActionsClusterRevision() {}

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

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

    ~SubscribeAttributeBridgedActionsClusterRevision() {}

    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);
        MTRBaseClusterBridgedActions * cluster = [[MTRBaseClusterBridgedActions alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedActions.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

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

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

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

private:
};

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

    ~ReadBasicDataModelRevision() {}

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

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

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

    ~SubscribeAttributeBasicDataModelRevision() {}

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

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicVendorName() {}

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

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

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

    ~SubscribeAttributeBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeVendorNameWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.VendorName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicVendorID() {}

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

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

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

    ~SubscribeAttributeBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeVendorIDWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.VendorID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicProductName() {}

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

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

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

    ~SubscribeAttributeBasicProductName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeProductNameWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ProductName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicProductID() {}

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

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

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

    ~SubscribeAttributeBasicProductID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeProductIDWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ProductID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicNodeLabel() {}

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

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

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

    ~WriteBasicNodeLabel() {}

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

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

private:
    chip::ByteSpan mValue;
};

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

    ~SubscribeAttributeBasicNodeLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNodeLabelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.NodeLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicLocation() {}

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

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

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

    ~WriteBasicLocation() {}

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

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

private:
    chip::ByteSpan mValue;
};

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

    ~SubscribeAttributeBasicLocation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLocationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.Location response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicHardwareVersion() {}

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

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

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

    ~SubscribeAttributeBasicHardwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeHardwareVersionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.HardwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicHardwareVersionString() {}

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

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

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

    ~SubscribeAttributeBasicHardwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeHardwareVersionStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.HardwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicSoftwareVersion() {}

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

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

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

    ~SubscribeAttributeBasicSoftwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSoftwareVersionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.SoftwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicSoftwareVersionString() {}

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

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

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

    ~SubscribeAttributeBasicSoftwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSoftwareVersionStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.SoftwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicManufacturingDate() {}

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

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

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

    ~SubscribeAttributeBasicManufacturingDate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeManufacturingDateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ManufacturingDate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicPartNumber() {}

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

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

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

    ~SubscribeAttributeBasicPartNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePartNumberWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.PartNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicProductURL() {}

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

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

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

    ~SubscribeAttributeBasicProductURL() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeProductURLWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ProductURL response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicProductLabel() {}

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

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

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

    ~SubscribeAttributeBasicProductLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeProductLabelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ProductLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicSerialNumber() {}

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

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

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

    ~SubscribeAttributeBasicSerialNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSerialNumberWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.SerialNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicLocalConfigDisabled() {}

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

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

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

    ~WriteBasicLocalConfigDisabled() {}

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

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

private:
    bool mValue;
};

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

    ~SubscribeAttributeBasicLocalConfigDisabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLocalConfigDisabledWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.LocalConfigDisabled response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicReachable() {}

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

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

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

    ~SubscribeAttributeBasicReachable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeReachableWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.Reachable response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicUniqueID() {}

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

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

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

    ~SubscribeAttributeBasicUniqueID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUniqueIDWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.UniqueID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicCapabilityMinima() {}

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

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

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

    ~SubscribeAttributeBasicCapabilityMinima() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCapabilityMinimaWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRBasicClusterCapabilityMinimaStruct * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.CapabilityMinima response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicGeneratedCommandList() {}

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

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

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

    ~SubscribeAttributeBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicAcceptedCommandList() {}

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

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

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

    ~SubscribeAttributeBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicAttributeList() {}

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

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

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

    ~SubscribeAttributeBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicFeatureMap() {}

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

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

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

    ~SubscribeAttributeBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

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

    ~ReadBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBasicClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OtaSoftwareUpdateProvider                                   | 0x0029 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * QueryImage                                                        |   0x00 |
| * ApplyUpdateRequest                                                |   0x02 |
| * NotifyUpdateApplied                                               |   0x04 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command QueryImage
 */
class OtaSoftwareUpdateProviderQueryImage : public ClusterCommand {
public:
    OtaSoftwareUpdateProviderQueryImage()
        : ClusterCommand("query-image")
        , mComplex_ProtocolsSupported(&mRequest.protocolsSupported)
    {
        AddArgument("VendorId", 0, UINT16_MAX, &mRequest.vendorId);
        AddArgument("ProductId", 0, UINT16_MAX, &mRequest.productId);
        AddArgument("SoftwareVersion", 0, UINT32_MAX, &mRequest.softwareVersion);
        AddArgument("ProtocolsSupported", &mComplex_ProtocolsSupported);
        AddArgument("HardwareVersion", 0, UINT16_MAX, &mRequest.hardwareVersion);
        AddArgument("Location", &mRequest.location);
        AddArgument("RequestorCanConsent", 0, 1, &mRequest.requestorCanConsent);
        AddArgument("MetadataForProvider", &mRequest.metadataForProvider);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint: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
                        completionHandler:^(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable values,
                            NSError * _Nullable error) {
                            NSLog(@"Values: %@", values);
                            responsesNeeded--;
                            if (error != nil) {
                                mError = error;
                                LogNSError("Error", error);
                            }
                            if (responsesNeeded == 0) {
                                SetCommandExitStatus(mError);
                            }
                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImage::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::OtaSoftwareUpdateProvider::OTADownloadProtocol>>
        mComplex_ProtocolsSupported;
};

/*
 * Command ApplyUpdateRequest
 */
class OtaSoftwareUpdateProviderApplyUpdateRequest : public ClusterCommand {
public:
    OtaSoftwareUpdateProviderApplyUpdateRequest()
        : ClusterCommand("apply-update-request")
    {
        AddArgument("UpdateToken", &mRequest.updateToken);
        AddArgument("NewVersion", 0, UINT32_MAX, &mRequest.newVersion);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint: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
                                completionHandler:^(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable values,
                                    NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateRequest::Type mRequest;
};

/*
 * Command NotifyUpdateApplied
 */
class OtaSoftwareUpdateProviderNotifyUpdateApplied : public ClusterCommand {
public:
    OtaSoftwareUpdateProviderNotifyUpdateApplied()
        : ClusterCommand("notify-update-applied")
    {
        AddArgument("UpdateToken", &mRequest.updateToken);
        AddArgument("SoftwareVersion", 0, UINT32_MAX, &mRequest.softwareVersion);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint: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
                                 completionHandler:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::NotifyUpdateApplied::Type mRequest;
};

/*
 * Attribute GeneratedCommandList
 */
class ReadOtaSoftwareUpdateProviderGeneratedCommandList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadOtaSoftwareUpdateProviderGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateProvider.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateProvider GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateProviderGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateProvider.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadOtaSoftwareUpdateProviderAcceptedCommandList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadOtaSoftwareUpdateProviderAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateProvider.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateProvider AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateProviderAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateProvider.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadOtaSoftwareUpdateProviderAttributeList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadOtaSoftwareUpdateProviderAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateProvider.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateProvider AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateProviderAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateProvider.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadOtaSoftwareUpdateProviderFeatureMap : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadOtaSoftwareUpdateProviderFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateProvider.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateProvider FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateProviderFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateProvider.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadOtaSoftwareUpdateProviderClusterRevision : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadOtaSoftwareUpdateProviderClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateProvider.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateProvider ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateProviderClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateProvider.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OtaSoftwareUpdateRequestor                                  | 0x002A |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * AnnounceOtaProvider                                               |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * DefaultOtaProviders                                               | 0x0000 |
| * UpdatePossible                                                    | 0x0001 |
| * UpdateState                                                       | 0x0002 |
| * UpdateStateProgress                                               | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StateTransition                                                   | 0x0000 |
| * VersionApplied                                                    | 0x0001 |
| * DownloadError                                                     | 0x0002 |
\*----------------------------------------------------------------------------*/

/*
 * Command AnnounceOtaProvider
 */
class OtaSoftwareUpdateRequestorAnnounceOtaProvider : public ClusterCommand {
public:
    OtaSoftwareUpdateRequestorAnnounceOtaProvider()
        : ClusterCommand("announce-ota-provider")
    {
        AddArgument("ProviderNodeId", 0, UINT64_MAX, &mRequest.providerNodeId);
        AddArgument("VendorId", 0, UINT16_MAX, &mRequest.vendorId);
        AddArgument("AnnouncementReason", 0, UINT8_MAX, &mRequest.announcementReason);
        AddArgument("MetadataForNode", &mRequest.metadataForNode);
        AddArgument("Endpoint", 0, UINT16_MAX, &mRequest.endpoint);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint: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
                                 completionHandler:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::Type mRequest;
};

/*
 * Attribute DefaultOtaProviders
 */
class ReadOtaSoftwareUpdateRequestorDefaultOtaProviders : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorDefaultOtaProviders()
        : ReadAttribute("default-ota-providers")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorDefaultOtaProviders() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster
            readAttributeDefaultOtaProvidersWithParams:params
                                     completionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                         NSLog(@"OtaSoftwareUpdateRequestor.DefaultOtaProviders response %@", [value description]);
                                         if (error != nil) {
                                             LogNSError("OtaSoftwareUpdateRequestor DefaultOtaProviders read Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }
};

class WriteOtaSoftwareUpdateRequestorDefaultOtaProviders : public WriteAttribute {
public:
    WriteOtaSoftwareUpdateRequestorDefaultOtaProviders()
        : WriteAttribute("default-ota-providers")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "default-ota-providers");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteOtaSoftwareUpdateRequestorDefaultOtaProviders() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTROtaSoftwareUpdateRequestorClusterProviderLocation * newElement_0;
                newElement_0 = [MTROtaSoftwareUpdateRequestorClusterProviderLocation new];
                newElement_0.providerNodeID = [NSNumber numberWithUnsignedLongLong:entry_0.providerNodeID];
                newElement_0.endpoint = [NSNumber numberWithUnsignedShort:entry_0.endpoint];
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeDefaultOtaProvidersWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("OtaSoftwareUpdateRequestor DefaultOtaProviders write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::OtaSoftwareUpdateRequestor::Structs::ProviderLocation::Type> mValue;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::OtaSoftwareUpdateRequestor::Structs::ProviderLocation::Type>>
        mComplex;
};

class SubscribeAttributeOtaSoftwareUpdateRequestorDefaultOtaProviders : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorDefaultOtaProviders()
        : SubscribeAttribute("default-ota-providers")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorDefaultOtaProviders() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDefaultOtaProvidersWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.DefaultOtaProviders response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UpdatePossible
 */
class ReadOtaSoftwareUpdateRequestorUpdatePossible : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorUpdatePossible()
        : ReadAttribute("update-possible")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorUpdatePossible() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeUpdatePossibleWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.UpdatePossible response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor UpdatePossible read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorUpdatePossible : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorUpdatePossible()
        : SubscribeAttribute("update-possible")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorUpdatePossible() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUpdatePossibleWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.UpdatePossible response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UpdateState
 */
class ReadOtaSoftwareUpdateRequestorUpdateState : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorUpdateState()
        : ReadAttribute("update-state")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorUpdateState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeUpdateStateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.UpdateState response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor UpdateState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorUpdateState : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorUpdateState()
        : SubscribeAttribute("update-state")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorUpdateState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUpdateStateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.UpdateState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UpdateStateProgress
 */
class ReadOtaSoftwareUpdateRequestorUpdateStateProgress : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorUpdateStateProgress()
        : ReadAttribute("update-state-progress")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorUpdateStateProgress() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeUpdateStateProgressWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.UpdateStateProgress response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor UpdateStateProgress read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorUpdateStateProgress : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorUpdateStateProgress()
        : SubscribeAttribute("update-state-progress")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorUpdateStateProgress() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUpdateStateProgressWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.UpdateStateProgress response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadOtaSoftwareUpdateRequestorGeneratedCommandList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadOtaSoftwareUpdateRequestorAcceptedCommandList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadOtaSoftwareUpdateRequestorAttributeList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadOtaSoftwareUpdateRequestorFeatureMap : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadOtaSoftwareUpdateRequestorClusterRevision : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster LocalizationConfiguration                                   | 0x002B |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * ActiveLocale                                                      | 0x0000 |
| * SupportedLocales                                                  | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute ActiveLocale
 */
class ReadLocalizationConfigurationActiveLocale : public ReadAttribute {
public:
    ReadLocalizationConfigurationActiveLocale()
        : ReadAttribute("active-locale")
    {
    }

    ~ReadLocalizationConfigurationActiveLocale() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeActiveLocaleWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.ActiveLocale response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration ActiveLocale read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteLocalizationConfigurationActiveLocale : public WriteAttribute {
public:
    WriteLocalizationConfigurationActiveLocale()
        : WriteAttribute("active-locale")
    {
        AddArgument("attr-name", "active-locale");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteLocalizationConfigurationActiveLocale() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeActiveLocaleWithValue:value
                                              params:params
                                   completionHandler:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("LocalizationConfiguration ActiveLocale write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeLocalizationConfigurationActiveLocale : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationActiveLocale()
        : SubscribeAttribute("active-locale")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationActiveLocale() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveLocaleWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.ActiveLocale response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedLocales
 */
class ReadLocalizationConfigurationSupportedLocales : public ReadAttribute {
public:
    ReadLocalizationConfigurationSupportedLocales()
        : ReadAttribute("supported-locales")
    {
    }

    ~ReadLocalizationConfigurationSupportedLocales() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeSupportedLocalesWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.SupportedLocales response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration SupportedLocales read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationSupportedLocales : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationSupportedLocales()
        : SubscribeAttribute("supported-locales")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationSupportedLocales() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSupportedLocalesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.SupportedLocales response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadLocalizationConfigurationGeneratedCommandList : public ReadAttribute {
public:
    ReadLocalizationConfigurationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadLocalizationConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadLocalizationConfigurationAcceptedCommandList : public ReadAttribute {
public:
    ReadLocalizationConfigurationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadLocalizationConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadLocalizationConfigurationAttributeList : public ReadAttribute {
public:
    ReadLocalizationConfigurationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadLocalizationConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadLocalizationConfigurationFeatureMap : public ReadAttribute {
public:
    ReadLocalizationConfigurationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadLocalizationConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadLocalizationConfigurationClusterRevision : public ReadAttribute {
public:
    ReadLocalizationConfigurationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadLocalizationConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster TimeFormatLocalization                                      | 0x002C |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * HourFormat                                                        | 0x0000 |
| * ActiveCalendarType                                                | 0x0001 |
| * SupportedCalendarTypes                                            | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute HourFormat
 */
class ReadTimeFormatLocalizationHourFormat : public ReadAttribute {
public:
    ReadTimeFormatLocalizationHourFormat()
        : ReadAttribute("hour-format")
    {
    }

    ~ReadTimeFormatLocalizationHourFormat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeHourFormatWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.HourFormat response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization HourFormat read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTimeFormatLocalizationHourFormat : public WriteAttribute {
public:
    WriteTimeFormatLocalizationHourFormat()
        : WriteAttribute("hour-format")
    {
        AddArgument("attr-name", "hour-format");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTimeFormatLocalizationHourFormat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeHourFormatWithValue:value
                                            params:params
                                 completionHandler:^(NSError * _Nullable error) {
                                     if (error != nil) {
                                         LogNSError("TimeFormatLocalization HourFormat write Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTimeFormatLocalizationHourFormat : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationHourFormat()
        : SubscribeAttribute("hour-format")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationHourFormat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeHourFormatWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.HourFormat response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveCalendarType
 */
class ReadTimeFormatLocalizationActiveCalendarType : public ReadAttribute {
public:
    ReadTimeFormatLocalizationActiveCalendarType()
        : ReadAttribute("active-calendar-type")
    {
    }

    ~ReadTimeFormatLocalizationActiveCalendarType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeActiveCalendarTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.ActiveCalendarType response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization ActiveCalendarType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTimeFormatLocalizationActiveCalendarType : public WriteAttribute {
public:
    WriteTimeFormatLocalizationActiveCalendarType()
        : WriteAttribute("active-calendar-type")
    {
        AddArgument("attr-name", "active-calendar-type");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTimeFormatLocalizationActiveCalendarType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeActiveCalendarTypeWithValue:value
                                                    params:params
                                         completionHandler:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("TimeFormatLocalization ActiveCalendarType write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTimeFormatLocalizationActiveCalendarType : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationActiveCalendarType()
        : SubscribeAttribute("active-calendar-type")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationActiveCalendarType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveCalendarTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.ActiveCalendarType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedCalendarTypes
 */
class ReadTimeFormatLocalizationSupportedCalendarTypes : public ReadAttribute {
public:
    ReadTimeFormatLocalizationSupportedCalendarTypes()
        : ReadAttribute("supported-calendar-types")
    {
    }

    ~ReadTimeFormatLocalizationSupportedCalendarTypes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeSupportedCalendarTypesWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.SupportedCalendarTypes response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization SupportedCalendarTypes read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationSupportedCalendarTypes : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationSupportedCalendarTypes()
        : SubscribeAttribute("supported-calendar-types")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationSupportedCalendarTypes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSupportedCalendarTypesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.SupportedCalendarTypes response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadTimeFormatLocalizationGeneratedCommandList : public ReadAttribute {
public:
    ReadTimeFormatLocalizationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadTimeFormatLocalizationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadTimeFormatLocalizationAcceptedCommandList : public ReadAttribute {
public:
    ReadTimeFormatLocalizationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadTimeFormatLocalizationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadTimeFormatLocalizationAttributeList : public ReadAttribute {
public:
    ReadTimeFormatLocalizationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadTimeFormatLocalizationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadTimeFormatLocalizationFeatureMap : public ReadAttribute {
public:
    ReadTimeFormatLocalizationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadTimeFormatLocalizationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadTimeFormatLocalizationClusterRevision : public ReadAttribute {
public:
    ReadTimeFormatLocalizationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadTimeFormatLocalizationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster UnitLocalization                                            | 0x002D |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * TemperatureUnit                                                   | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute TemperatureUnit
 */
class ReadUnitLocalizationTemperatureUnit : public ReadAttribute {
public:
    ReadUnitLocalizationTemperatureUnit()
        : ReadAttribute("temperature-unit")
    {
    }

    ~ReadUnitLocalizationTemperatureUnit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeTemperatureUnitWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.TemperatureUnit response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization TemperatureUnit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitLocalizationTemperatureUnit : public WriteAttribute {
public:
    WriteUnitLocalizationTemperatureUnit()
        : WriteAttribute("temperature-unit")
    {
        AddArgument("attr-name", "temperature-unit");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitLocalizationTemperatureUnit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeTemperatureUnitWithValue:value
                                                 params:params
                                      completionHandler:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("UnitLocalization TemperatureUnit write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitLocalizationTemperatureUnit : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationTemperatureUnit()
        : SubscribeAttribute("temperature-unit")
    {
    }

    ~SubscribeAttributeUnitLocalizationTemperatureUnit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTemperatureUnitWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.TemperatureUnit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadUnitLocalizationGeneratedCommandList : public ReadAttribute {
public:
    ReadUnitLocalizationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadUnitLocalizationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitLocalizationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeUnitLocalizationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadUnitLocalizationAcceptedCommandList : public ReadAttribute {
public:
    ReadUnitLocalizationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadUnitLocalizationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitLocalizationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeUnitLocalizationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadUnitLocalizationAttributeList : public ReadAttribute {
public:
    ReadUnitLocalizationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadUnitLocalizationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitLocalizationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeUnitLocalizationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadUnitLocalizationFeatureMap : public ReadAttribute {
public:
    ReadUnitLocalizationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadUnitLocalizationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitLocalizationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeUnitLocalizationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadUnitLocalizationClusterRevision : public ReadAttribute {
public:
    ReadUnitLocalizationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadUnitLocalizationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitLocalizationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeUnitLocalizationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster PowerSourceConfiguration                                    | 0x002E |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Sources                                                           | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute Sources
 */
class ReadPowerSourceConfigurationSources : public ReadAttribute {
public:
    ReadPowerSourceConfigurationSources()
        : ReadAttribute("sources")
    {
    }

    ~ReadPowerSourceConfigurationSources() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeSourcesWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.Sources response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration Sources read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationSources : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationSources()
        : SubscribeAttribute("sources")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationSources() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSourcesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.Sources response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadPowerSourceConfigurationGeneratedCommandList : public ReadAttribute {
public:
    ReadPowerSourceConfigurationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadPowerSourceConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadPowerSourceConfigurationAcceptedCommandList : public ReadAttribute {
public:
    ReadPowerSourceConfigurationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadPowerSourceConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadPowerSourceConfigurationAttributeList : public ReadAttribute {
public:
    ReadPowerSourceConfigurationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadPowerSourceConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadPowerSourceConfigurationFeatureMap : public ReadAttribute {
public:
    ReadPowerSourceConfigurationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadPowerSourceConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadPowerSourceConfigurationClusterRevision : public ReadAttribute {
public:
    ReadPowerSourceConfigurationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadPowerSourceConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster PowerSource                                                 | 0x002F |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Status                                                            | 0x0000 |
| * Order                                                             | 0x0001 |
| * Description                                                       | 0x0002 |
| * WiredAssessedInputVoltage                                         | 0x0003 |
| * WiredAssessedInputFrequency                                       | 0x0004 |
| * WiredCurrentType                                                  | 0x0005 |
| * WiredAssessedCurrent                                              | 0x0006 |
| * WiredNominalVoltage                                               | 0x0007 |
| * WiredMaximumCurrent                                               | 0x0008 |
| * WiredPresent                                                      | 0x0009 |
| * ActiveWiredFaults                                                 | 0x000A |
| * BatVoltage                                                        | 0x000B |
| * BatPercentRemaining                                               | 0x000C |
| * BatTimeRemaining                                                  | 0x000D |
| * BatChargeLevel                                                    | 0x000E |
| * BatReplacementNeeded                                              | 0x000F |
| * BatReplaceability                                                 | 0x0010 |
| * BatPresent                                                        | 0x0011 |
| * ActiveBatFaults                                                   | 0x0012 |
| * BatReplacementDescription                                         | 0x0013 |
| * BatCommonDesignation                                              | 0x0014 |
| * BatANSIDesignation                                                | 0x0015 |
| * BatIECDesignation                                                 | 0x0016 |
| * BatApprovedChemistry                                              | 0x0017 |
| * BatCapacity                                                       | 0x0018 |
| * BatQuantity                                                       | 0x0019 |
| * BatChargeState                                                    | 0x001A |
| * BatTimeToFullCharge                                               | 0x001B |
| * BatFunctionalWhileCharging                                        | 0x001C |
| * BatChargingCurrent                                                | 0x001D |
| * ActiveBatChargeFaults                                             | 0x001E |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute Status
 */
class ReadPowerSourceStatus : public ReadAttribute {
public:
    ReadPowerSourceStatus()
        : ReadAttribute("status")
    {
    }

    ~ReadPowerSourceStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeStatusWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.Status response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource Status read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceStatus : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceStatus()
        : SubscribeAttribute("status")
    {
    }

    ~SubscribeAttributePowerSourceStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeStatusWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.Status response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Order
 */
class ReadPowerSourceOrder : public ReadAttribute {
public:
    ReadPowerSourceOrder()
        : ReadAttribute("order")
    {
    }

    ~ReadPowerSourceOrder() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeOrderWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.Order response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource Order read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceOrder : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceOrder()
        : SubscribeAttribute("order")
    {
    }

    ~SubscribeAttributePowerSourceOrder() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOrderWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.Order response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Description
 */
class ReadPowerSourceDescription : public ReadAttribute {
public:
    ReadPowerSourceDescription()
        : ReadAttribute("description")
    {
    }

    ~ReadPowerSourceDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeDescriptionWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.Description response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource Description read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceDescription : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceDescription()
        : SubscribeAttribute("description")
    {
    }

    ~SubscribeAttributePowerSourceDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDescriptionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.Description response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredAssessedInputVoltage
 */
class ReadPowerSourceWiredAssessedInputVoltage : public ReadAttribute {
public:
    ReadPowerSourceWiredAssessedInputVoltage()
        : ReadAttribute("wired-assessed-input-voltage")
    {
    }

    ~ReadPowerSourceWiredAssessedInputVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster
            readAttributeWiredAssessedInputVoltageWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredAssessedInputVoltage response %@", [value description]);
                if (error != nil) {
                    LogNSError("PowerSource WiredAssessedInputVoltage read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredAssessedInputVoltage : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredAssessedInputVoltage()
        : SubscribeAttribute("wired-assessed-input-voltage")
    {
    }

    ~SubscribeAttributePowerSourceWiredAssessedInputVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWiredAssessedInputVoltageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredAssessedInputVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredAssessedInputFrequency
 */
class ReadPowerSourceWiredAssessedInputFrequency : public ReadAttribute {
public:
    ReadPowerSourceWiredAssessedInputFrequency()
        : ReadAttribute("wired-assessed-input-frequency")
    {
    }

    ~ReadPowerSourceWiredAssessedInputFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster
            readAttributeWiredAssessedInputFrequencyWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredAssessedInputFrequency response %@", [value description]);
                if (error != nil) {
                    LogNSError("PowerSource WiredAssessedInputFrequency read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredAssessedInputFrequency : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredAssessedInputFrequency()
        : SubscribeAttribute("wired-assessed-input-frequency")
    {
    }

    ~SubscribeAttributePowerSourceWiredAssessedInputFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWiredAssessedInputFrequencyWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredAssessedInputFrequency response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredCurrentType
 */
class ReadPowerSourceWiredCurrentType : public ReadAttribute {
public:
    ReadPowerSourceWiredCurrentType()
        : ReadAttribute("wired-current-type")
    {
    }

    ~ReadPowerSourceWiredCurrentType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredCurrentTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredCurrentType response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredCurrentType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredCurrentType : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredCurrentType()
        : SubscribeAttribute("wired-current-type")
    {
    }

    ~SubscribeAttributePowerSourceWiredCurrentType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWiredCurrentTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredCurrentType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredAssessedCurrent
 */
class ReadPowerSourceWiredAssessedCurrent : public ReadAttribute {
public:
    ReadPowerSourceWiredAssessedCurrent()
        : ReadAttribute("wired-assessed-current")
    {
    }

    ~ReadPowerSourceWiredAssessedCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredAssessedCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredAssessedCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredAssessedCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredAssessedCurrent : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredAssessedCurrent()
        : SubscribeAttribute("wired-assessed-current")
    {
    }

    ~SubscribeAttributePowerSourceWiredAssessedCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWiredAssessedCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredAssessedCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredNominalVoltage
 */
class ReadPowerSourceWiredNominalVoltage : public ReadAttribute {
public:
    ReadPowerSourceWiredNominalVoltage()
        : ReadAttribute("wired-nominal-voltage")
    {
    }

    ~ReadPowerSourceWiredNominalVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredNominalVoltageWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredNominalVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredNominalVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredNominalVoltage : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredNominalVoltage()
        : SubscribeAttribute("wired-nominal-voltage")
    {
    }

    ~SubscribeAttributePowerSourceWiredNominalVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWiredNominalVoltageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredNominalVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredMaximumCurrent
 */
class ReadPowerSourceWiredMaximumCurrent : public ReadAttribute {
public:
    ReadPowerSourceWiredMaximumCurrent()
        : ReadAttribute("wired-maximum-current")
    {
    }

    ~ReadPowerSourceWiredMaximumCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredMaximumCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredMaximumCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredMaximumCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredMaximumCurrent : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredMaximumCurrent()
        : SubscribeAttribute("wired-maximum-current")
    {
    }

    ~SubscribeAttributePowerSourceWiredMaximumCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWiredMaximumCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredMaximumCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredPresent
 */
class ReadPowerSourceWiredPresent : public ReadAttribute {
public:
    ReadPowerSourceWiredPresent()
        : ReadAttribute("wired-present")
    {
    }

    ~ReadPowerSourceWiredPresent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredPresentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredPresent response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredPresent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredPresent : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredPresent()
        : SubscribeAttribute("wired-present")
    {
    }

    ~SubscribeAttributePowerSourceWiredPresent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWiredPresentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredPresent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveWiredFaults
 */
class ReadPowerSourceActiveWiredFaults : public ReadAttribute {
public:
    ReadPowerSourceActiveWiredFaults()
        : ReadAttribute("active-wired-faults")
    {
    }

    ~ReadPowerSourceActiveWiredFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeActiveWiredFaultsWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.ActiveWiredFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource ActiveWiredFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceActiveWiredFaults : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceActiveWiredFaults()
        : SubscribeAttribute("active-wired-faults")
    {
    }

    ~SubscribeAttributePowerSourceActiveWiredFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveWiredFaultsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.ActiveWiredFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatVoltage
 */
class ReadPowerSourceBatVoltage : public ReadAttribute {
public:
    ReadPowerSourceBatVoltage()
        : ReadAttribute("bat-voltage")
    {
    }

    ~ReadPowerSourceBatVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatVoltageWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatVoltage : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatVoltage()
        : SubscribeAttribute("bat-voltage")
    {
    }

    ~SubscribeAttributePowerSourceBatVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatVoltageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatPercentRemaining
 */
class ReadPowerSourceBatPercentRemaining : public ReadAttribute {
public:
    ReadPowerSourceBatPercentRemaining()
        : ReadAttribute("bat-percent-remaining")
    {
    }

    ~ReadPowerSourceBatPercentRemaining() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatPercentRemainingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatPercentRemaining response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatPercentRemaining read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatPercentRemaining : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatPercentRemaining()
        : SubscribeAttribute("bat-percent-remaining")
    {
    }

    ~SubscribeAttributePowerSourceBatPercentRemaining() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatPercentRemainingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatPercentRemaining response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatTimeRemaining
 */
class ReadPowerSourceBatTimeRemaining : public ReadAttribute {
public:
    ReadPowerSourceBatTimeRemaining()
        : ReadAttribute("bat-time-remaining")
    {
    }

    ~ReadPowerSourceBatTimeRemaining() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatTimeRemainingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatTimeRemaining response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatTimeRemaining read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatTimeRemaining : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatTimeRemaining()
        : SubscribeAttribute("bat-time-remaining")
    {
    }

    ~SubscribeAttributePowerSourceBatTimeRemaining() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatTimeRemainingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatTimeRemaining response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatChargeLevel
 */
class ReadPowerSourceBatChargeLevel : public ReadAttribute {
public:
    ReadPowerSourceBatChargeLevel()
        : ReadAttribute("bat-charge-level")
    {
    }

    ~ReadPowerSourceBatChargeLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatChargeLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatChargeLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatChargeLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatChargeLevel : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatChargeLevel()
        : SubscribeAttribute("bat-charge-level")
    {
    }

    ~SubscribeAttributePowerSourceBatChargeLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatChargeLevelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatChargeLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatReplacementNeeded
 */
class ReadPowerSourceBatReplacementNeeded : public ReadAttribute {
public:
    ReadPowerSourceBatReplacementNeeded()
        : ReadAttribute("bat-replacement-needed")
    {
    }

    ~ReadPowerSourceBatReplacementNeeded() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatReplacementNeededWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatReplacementNeeded response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatReplacementNeeded read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatReplacementNeeded : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatReplacementNeeded()
        : SubscribeAttribute("bat-replacement-needed")
    {
    }

    ~SubscribeAttributePowerSourceBatReplacementNeeded() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatReplacementNeededWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatReplacementNeeded response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatReplaceability
 */
class ReadPowerSourceBatReplaceability : public ReadAttribute {
public:
    ReadPowerSourceBatReplaceability()
        : ReadAttribute("bat-replaceability")
    {
    }

    ~ReadPowerSourceBatReplaceability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatReplaceabilityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatReplaceability response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatReplaceability read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatReplaceability : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatReplaceability()
        : SubscribeAttribute("bat-replaceability")
    {
    }

    ~SubscribeAttributePowerSourceBatReplaceability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatReplaceabilityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatReplaceability response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatPresent
 */
class ReadPowerSourceBatPresent : public ReadAttribute {
public:
    ReadPowerSourceBatPresent()
        : ReadAttribute("bat-present")
    {
    }

    ~ReadPowerSourceBatPresent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatPresentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatPresent response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatPresent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatPresent : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatPresent()
        : SubscribeAttribute("bat-present")
    {
    }

    ~SubscribeAttributePowerSourceBatPresent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatPresentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatPresent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveBatFaults
 */
class ReadPowerSourceActiveBatFaults : public ReadAttribute {
public:
    ReadPowerSourceActiveBatFaults()
        : ReadAttribute("active-bat-faults")
    {
    }

    ~ReadPowerSourceActiveBatFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeActiveBatFaultsWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.ActiveBatFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource ActiveBatFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceActiveBatFaults : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceActiveBatFaults()
        : SubscribeAttribute("active-bat-faults")
    {
    }

    ~SubscribeAttributePowerSourceActiveBatFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveBatFaultsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.ActiveBatFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatReplacementDescription
 */
class ReadPowerSourceBatReplacementDescription : public ReadAttribute {
public:
    ReadPowerSourceBatReplacementDescription()
        : ReadAttribute("bat-replacement-description")
    {
    }

    ~ReadPowerSourceBatReplacementDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster
            readAttributeBatReplacementDescriptionWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatReplacementDescription response %@", [value description]);
                if (error != nil) {
                    LogNSError("PowerSource BatReplacementDescription read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatReplacementDescription : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatReplacementDescription()
        : SubscribeAttribute("bat-replacement-description")
    {
    }

    ~SubscribeAttributePowerSourceBatReplacementDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatReplacementDescriptionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatReplacementDescription response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatCommonDesignation
 */
class ReadPowerSourceBatCommonDesignation : public ReadAttribute {
public:
    ReadPowerSourceBatCommonDesignation()
        : ReadAttribute("bat-common-designation")
    {
    }

    ~ReadPowerSourceBatCommonDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatCommonDesignationWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatCommonDesignation response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatCommonDesignation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatCommonDesignation : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatCommonDesignation()
        : SubscribeAttribute("bat-common-designation")
    {
    }

    ~SubscribeAttributePowerSourceBatCommonDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatCommonDesignationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatCommonDesignation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatANSIDesignation
 */
class ReadPowerSourceBatANSIDesignation : public ReadAttribute {
public:
    ReadPowerSourceBatANSIDesignation()
        : ReadAttribute("bat-ansidesignation")
    {
    }

    ~ReadPowerSourceBatANSIDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatANSIDesignationWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatANSIDesignation response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatANSIDesignation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatANSIDesignation : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatANSIDesignation()
        : SubscribeAttribute("bat-ansidesignation")
    {
    }

    ~SubscribeAttributePowerSourceBatANSIDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatANSIDesignationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatANSIDesignation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatIECDesignation
 */
class ReadPowerSourceBatIECDesignation : public ReadAttribute {
public:
    ReadPowerSourceBatIECDesignation()
        : ReadAttribute("bat-iecdesignation")
    {
    }

    ~ReadPowerSourceBatIECDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatIECDesignationWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatIECDesignation response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatIECDesignation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatIECDesignation : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatIECDesignation()
        : SubscribeAttribute("bat-iecdesignation")
    {
    }

    ~SubscribeAttributePowerSourceBatIECDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatIECDesignationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatIECDesignation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatApprovedChemistry
 */
class ReadPowerSourceBatApprovedChemistry : public ReadAttribute {
public:
    ReadPowerSourceBatApprovedChemistry()
        : ReadAttribute("bat-approved-chemistry")
    {
    }

    ~ReadPowerSourceBatApprovedChemistry() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatApprovedChemistryWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatApprovedChemistry response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatApprovedChemistry read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatApprovedChemistry : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatApprovedChemistry()
        : SubscribeAttribute("bat-approved-chemistry")
    {
    }

    ~SubscribeAttributePowerSourceBatApprovedChemistry() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatApprovedChemistryWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatApprovedChemistry response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatCapacity
 */
class ReadPowerSourceBatCapacity : public ReadAttribute {
public:
    ReadPowerSourceBatCapacity()
        : ReadAttribute("bat-capacity")
    {
    }

    ~ReadPowerSourceBatCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatCapacityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatCapacity response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatCapacity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatCapacity : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatCapacity()
        : SubscribeAttribute("bat-capacity")
    {
    }

    ~SubscribeAttributePowerSourceBatCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatCapacityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatCapacity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatQuantity
 */
class ReadPowerSourceBatQuantity : public ReadAttribute {
public:
    ReadPowerSourceBatQuantity()
        : ReadAttribute("bat-quantity")
    {
    }

    ~ReadPowerSourceBatQuantity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatQuantityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatQuantity response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatQuantity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatQuantity : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatQuantity()
        : SubscribeAttribute("bat-quantity")
    {
    }

    ~SubscribeAttributePowerSourceBatQuantity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatQuantityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatQuantity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatChargeState
 */
class ReadPowerSourceBatChargeState : public ReadAttribute {
public:
    ReadPowerSourceBatChargeState()
        : ReadAttribute("bat-charge-state")
    {
    }

    ~ReadPowerSourceBatChargeState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatChargeStateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatChargeState response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatChargeState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatChargeState : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatChargeState()
        : SubscribeAttribute("bat-charge-state")
    {
    }

    ~SubscribeAttributePowerSourceBatChargeState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatChargeStateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatChargeState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatTimeToFullCharge
 */
class ReadPowerSourceBatTimeToFullCharge : public ReadAttribute {
public:
    ReadPowerSourceBatTimeToFullCharge()
        : ReadAttribute("bat-time-to-full-charge")
    {
    }

    ~ReadPowerSourceBatTimeToFullCharge() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatTimeToFullChargeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatTimeToFullCharge response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatTimeToFullCharge read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatTimeToFullCharge : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatTimeToFullCharge()
        : SubscribeAttribute("bat-time-to-full-charge")
    {
    }

    ~SubscribeAttributePowerSourceBatTimeToFullCharge() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatTimeToFullChargeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatTimeToFullCharge response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatFunctionalWhileCharging
 */
class ReadPowerSourceBatFunctionalWhileCharging : public ReadAttribute {
public:
    ReadPowerSourceBatFunctionalWhileCharging()
        : ReadAttribute("bat-functional-while-charging")
    {
    }

    ~ReadPowerSourceBatFunctionalWhileCharging() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster
            readAttributeBatFunctionalWhileChargingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatFunctionalWhileCharging response %@", [value description]);
                if (error != nil) {
                    LogNSError("PowerSource BatFunctionalWhileCharging read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatFunctionalWhileCharging : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatFunctionalWhileCharging()
        : SubscribeAttribute("bat-functional-while-charging")
    {
    }

    ~SubscribeAttributePowerSourceBatFunctionalWhileCharging() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatFunctionalWhileChargingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatFunctionalWhileCharging response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatChargingCurrent
 */
class ReadPowerSourceBatChargingCurrent : public ReadAttribute {
public:
    ReadPowerSourceBatChargingCurrent()
        : ReadAttribute("bat-charging-current")
    {
    }

    ~ReadPowerSourceBatChargingCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000001D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatChargingCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatChargingCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatChargingCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatChargingCurrent : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatChargingCurrent()
        : SubscribeAttribute("bat-charging-current")
    {
    }

    ~SubscribeAttributePowerSourceBatChargingCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000001D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBatChargingCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatChargingCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveBatChargeFaults
 */
class ReadPowerSourceActiveBatChargeFaults : public ReadAttribute {
public:
    ReadPowerSourceActiveBatChargeFaults()
        : ReadAttribute("active-bat-charge-faults")
    {
    }

    ~ReadPowerSourceActiveBatChargeFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000001E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeActiveBatChargeFaultsWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.ActiveBatChargeFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource ActiveBatChargeFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceActiveBatChargeFaults : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceActiveBatChargeFaults()
        : SubscribeAttribute("active-bat-charge-faults")
    {
    }

    ~SubscribeAttributePowerSourceActiveBatChargeFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000001E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveBatChargeFaultsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.ActiveBatChargeFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadPowerSourceGeneratedCommandList : public ReadAttribute {
public:
    ReadPowerSourceGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadPowerSourceGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributePowerSourceGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadPowerSourceAcceptedCommandList : public ReadAttribute {
public:
    ReadPowerSourceAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadPowerSourceAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributePowerSourceAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadPowerSourceAttributeList : public ReadAttribute {
public:
    ReadPowerSourceAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadPowerSourceAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributePowerSourceAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadPowerSourceFeatureMap : public ReadAttribute {
public:
    ReadPowerSourceFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadPowerSourceFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributePowerSourceFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadPowerSourceClusterRevision : public ReadAttribute {
public:
    ReadPowerSourceClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadPowerSourceClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributePowerSourceClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster GeneralCommissioning                                        | 0x0030 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ArmFailSafe                                                       |   0x00 |
| * SetRegulatoryConfig                                               |   0x02 |
| * CommissioningComplete                                             |   0x04 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Breadcrumb                                                        | 0x0000 |
| * BasicCommissioningInfo                                            | 0x0001 |
| * RegulatoryConfig                                                  | 0x0002 |
| * LocationCapability                                                | 0x0003 |
| * SupportsConcurrentConnection                                      | 0x0004 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ArmFailSafe
 */
class GeneralCommissioningArmFailSafe : public ClusterCommand {
public:
    GeneralCommissioningArmFailSafe()
        : ClusterCommand("arm-fail-safe")
    {
        AddArgument("ExpiryLengthSeconds", 0, UINT16_MAX, &mRequest.expiryLengthSeconds);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint: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
                         completionHandler:^(MTRGeneralCommissioningClusterArmFailSafeResponseParams * _Nullable values,
                             NSError * _Nullable error) {
                             NSLog(@"Values: %@", values);
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GeneralCommissioning::Commands::ArmFailSafe::Type mRequest;
};

/*
 * Command SetRegulatoryConfig
 */
class GeneralCommissioningSetRegulatoryConfig : public ClusterCommand {
public:
    GeneralCommissioningSetRegulatoryConfig()
        : ClusterCommand("set-regulatory-config")
    {
        AddArgument("NewRegulatoryConfig", 0, UINT8_MAX, &mRequest.newRegulatoryConfig);
        AddArgument("CountryCode", &mRequest.countryCode);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint: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
                            completionHandler:^(MTRGeneralCommissioningClusterSetRegulatoryConfigResponseParams * _Nullable values,
                                NSError * _Nullable error) {
                                NSLog(@"Values: %@", values);
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GeneralCommissioning::Commands::SetRegulatoryConfig::Type mRequest;
};

/*
 * Command CommissioningComplete
 */
class GeneralCommissioningCommissioningComplete : public ClusterCommand {
public:
    GeneralCommissioningCommissioningComplete()
        : ClusterCommand("commissioning-complete")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint: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
                                   completionHandler:^(
                                       MTRGeneralCommissioningClusterCommissioningCompleteResponseParams * _Nullable values,
                                       NSError * _Nullable error) {
                                       NSLog(@"Values: %@", values);
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute Breadcrumb
 */
class ReadGeneralCommissioningBreadcrumb : public ReadAttribute {
public:
    ReadGeneralCommissioningBreadcrumb()
        : ReadAttribute("breadcrumb")
    {
    }

    ~ReadGeneralCommissioningBreadcrumb() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeBreadcrumbWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.Breadcrumb response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning Breadcrumb read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteGeneralCommissioningBreadcrumb : public WriteAttribute {
public:
    WriteGeneralCommissioningBreadcrumb()
        : WriteAttribute("breadcrumb")
    {
        AddArgument("attr-name", "breadcrumb");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteGeneralCommissioningBreadcrumb() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeBreadcrumbWithValue:value
                                            params:params
                                 completionHandler:^(NSError * _Nullable error) {
                                     if (error != nil) {
                                         LogNSError("GeneralCommissioning Breadcrumb write Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeGeneralCommissioningBreadcrumb : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningBreadcrumb()
        : SubscribeAttribute("breadcrumb")
    {
    }

    ~SubscribeAttributeGeneralCommissioningBreadcrumb() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBreadcrumbWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.Breadcrumb response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BasicCommissioningInfo
 */
class ReadGeneralCommissioningBasicCommissioningInfo : public ReadAttribute {
public:
    ReadGeneralCommissioningBasicCommissioningInfo()
        : ReadAttribute("basic-commissioning-info")
    {
    }

    ~ReadGeneralCommissioningBasicCommissioningInfo() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeBasicCommissioningInfoWithCompletionHandler:^(
            MTRGeneralCommissioningClusterBasicCommissioningInfo * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.BasicCommissioningInfo response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning BasicCommissioningInfo read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningBasicCommissioningInfo : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningBasicCommissioningInfo()
        : SubscribeAttribute("basic-commissioning-info")
    {
    }

    ~SubscribeAttributeGeneralCommissioningBasicCommissioningInfo() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBasicCommissioningInfoWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRGeneralCommissioningClusterBasicCommissioningInfo * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.BasicCommissioningInfo response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RegulatoryConfig
 */
class ReadGeneralCommissioningRegulatoryConfig : public ReadAttribute {
public:
    ReadGeneralCommissioningRegulatoryConfig()
        : ReadAttribute("regulatory-config")
    {
    }

    ~ReadGeneralCommissioningRegulatoryConfig() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeRegulatoryConfigWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.RegulatoryConfig response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning RegulatoryConfig read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningRegulatoryConfig : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningRegulatoryConfig()
        : SubscribeAttribute("regulatory-config")
    {
    }

    ~SubscribeAttributeGeneralCommissioningRegulatoryConfig() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRegulatoryConfigWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.RegulatoryConfig response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LocationCapability
 */
class ReadGeneralCommissioningLocationCapability : public ReadAttribute {
public:
    ReadGeneralCommissioningLocationCapability()
        : ReadAttribute("location-capability")
    {
    }

    ~ReadGeneralCommissioningLocationCapability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLocationCapabilityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.LocationCapability response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning LocationCapability read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningLocationCapability : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningLocationCapability()
        : SubscribeAttribute("location-capability")
    {
    }

    ~SubscribeAttributeGeneralCommissioningLocationCapability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLocationCapabilityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.LocationCapability response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportsConcurrentConnection
 */
class ReadGeneralCommissioningSupportsConcurrentConnection : public ReadAttribute {
public:
    ReadGeneralCommissioningSupportsConcurrentConnection()
        : ReadAttribute("supports-concurrent-connection")
    {
    }

    ~ReadGeneralCommissioningSupportsConcurrentConnection() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeSupportsConcurrentConnectionWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.SupportsConcurrentConnection response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning SupportsConcurrentConnection read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningSupportsConcurrentConnection : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningSupportsConcurrentConnection()
        : SubscribeAttribute("supports-concurrent-connection")
    {
    }

    ~SubscribeAttributeGeneralCommissioningSupportsConcurrentConnection() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSupportsConcurrentConnectionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.SupportsConcurrentConnection response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadGeneralCommissioningGeneratedCommandList : public ReadAttribute {
public:
    ReadGeneralCommissioningGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadGeneralCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeGeneralCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadGeneralCommissioningAcceptedCommandList : public ReadAttribute {
public:
    ReadGeneralCommissioningAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadGeneralCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeGeneralCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadGeneralCommissioningAttributeList : public ReadAttribute {
public:
    ReadGeneralCommissioningAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadGeneralCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeGeneralCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadGeneralCommissioningFeatureMap : public ReadAttribute {
public:
    ReadGeneralCommissioningFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadGeneralCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeGeneralCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadGeneralCommissioningClusterRevision : public ReadAttribute {
public:
    ReadGeneralCommissioningClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadGeneralCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeGeneralCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster NetworkCommissioning                                        | 0x0031 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ScanNetworks                                                      |   0x00 |
| * AddOrUpdateWiFiNetwork                                            |   0x02 |
| * AddOrUpdateThreadNetwork                                          |   0x03 |
| * RemoveNetwork                                                     |   0x04 |
| * ConnectNetwork                                                    |   0x06 |
| * ReorderNetwork                                                    |   0x08 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MaxNetworks                                                       | 0x0000 |
| * Networks                                                          | 0x0001 |
| * ScanMaxTimeSeconds                                                | 0x0002 |
| * ConnectMaxTimeSeconds                                             | 0x0003 |
| * InterfaceEnabled                                                  | 0x0004 |
| * LastNetworkingStatus                                              | 0x0005 |
| * LastNetworkID                                                     | 0x0006 |
| * LastConnectErrorValue                                             | 0x0007 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ScanNetworks
 */
class NetworkCommissioningScanNetworks : public ClusterCommand {
public:
    NetworkCommissioningScanNetworks()
        : ClusterCommand("scan-networks")
    {
        AddArgument("Ssid", &mRequest.ssid);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint: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
                          completionHandler:^(MTRNetworkCommissioningClusterScanNetworksResponseParams * _Nullable values,
                              NSError * _Nullable error) {
                              NSLog(@"Values: %@", values);
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::ScanNetworks::Type mRequest;
};

/*
 * Command AddOrUpdateWiFiNetwork
 */
class NetworkCommissioningAddOrUpdateWiFiNetwork : public ClusterCommand {
public:
    NetworkCommissioningAddOrUpdateWiFiNetwork()
        : ClusterCommand("add-or-update-wi-fi-network")
    {
        AddArgument("Ssid", &mRequest.ssid);
        AddArgument("Credentials", &mRequest.credentials);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint: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
                               completionHandler:^(MTRNetworkCommissioningClusterNetworkConfigResponseParams * _Nullable values,
                                   NSError * _Nullable error) {
                                   NSLog(@"Values: %@", values);
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::AddOrUpdateWiFiNetwork::Type mRequest;
};

/*
 * Command AddOrUpdateThreadNetwork
 */
class NetworkCommissioningAddOrUpdateThreadNetwork : public ClusterCommand {
public:
    NetworkCommissioningAddOrUpdateThreadNetwork()
        : ClusterCommand("add-or-update-thread-network")
    {
        AddArgument("OperationalDataset", &mRequest.operationalDataset);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint: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
                                 completionHandler:^(MTRNetworkCommissioningClusterNetworkConfigResponseParams * _Nullable values,
                                     NSError * _Nullable error) {
                                     NSLog(@"Values: %@", values);
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::AddOrUpdateThreadNetwork::Type mRequest;
};

/*
 * Command RemoveNetwork
 */
class NetworkCommissioningRemoveNetwork : public ClusterCommand {
public:
    NetworkCommissioningRemoveNetwork()
        : ClusterCommand("remove-network")
    {
        AddArgument("NetworkID", &mRequest.networkID);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint: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
                           completionHandler:^(MTRNetworkCommissioningClusterNetworkConfigResponseParams * _Nullable values,
                               NSError * _Nullable error) {
                               NSLog(@"Values: %@", values);
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::RemoveNetwork::Type mRequest;
};

/*
 * Command ConnectNetwork
 */
class NetworkCommissioningConnectNetwork : public ClusterCommand {
public:
    NetworkCommissioningConnectNetwork()
        : ClusterCommand("connect-network")
    {
        AddArgument("NetworkID", &mRequest.networkID);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint: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
                            completionHandler:^(MTRNetworkCommissioningClusterConnectNetworkResponseParams * _Nullable values,
                                NSError * _Nullable error) {
                                NSLog(@"Values: %@", values);
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::ConnectNetwork::Type mRequest;
};

/*
 * Command ReorderNetwork
 */
class NetworkCommissioningReorderNetwork : public ClusterCommand {
public:
    NetworkCommissioningReorderNetwork()
        : ClusterCommand("reorder-network")
    {
        AddArgument("NetworkID", &mRequest.networkID);
        AddArgument("NetworkIndex", 0, UINT8_MAX, &mRequest.networkIndex);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint: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
                            completionHandler:^(MTRNetworkCommissioningClusterNetworkConfigResponseParams * _Nullable values,
                                NSError * _Nullable error) {
                                NSLog(@"Values: %@", values);
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::ReorderNetwork::Type mRequest;
};

/*
 * Attribute MaxNetworks
 */
class ReadNetworkCommissioningMaxNetworks : public ReadAttribute {
public:
    ReadNetworkCommissioningMaxNetworks()
        : ReadAttribute("max-networks")
    {
    }

    ~ReadNetworkCommissioningMaxNetworks() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeMaxNetworksWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.MaxNetworks response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning MaxNetworks read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningMaxNetworks : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningMaxNetworks()
        : SubscribeAttribute("max-networks")
    {
    }

    ~SubscribeAttributeNetworkCommissioningMaxNetworks() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxNetworksWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.MaxNetworks response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Networks
 */
class ReadNetworkCommissioningNetworks : public ReadAttribute {
public:
    ReadNetworkCommissioningNetworks()
        : ReadAttribute("networks")
    {
    }

    ~ReadNetworkCommissioningNetworks() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeNetworksWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.Networks response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning Networks read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningNetworks : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningNetworks()
        : SubscribeAttribute("networks")
    {
    }

    ~SubscribeAttributeNetworkCommissioningNetworks() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNetworksWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.Networks response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ScanMaxTimeSeconds
 */
class ReadNetworkCommissioningScanMaxTimeSeconds : public ReadAttribute {
public:
    ReadNetworkCommissioningScanMaxTimeSeconds()
        : ReadAttribute("scan-max-time-seconds")
    {
    }

    ~ReadNetworkCommissioningScanMaxTimeSeconds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeScanMaxTimeSecondsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.ScanMaxTimeSeconds response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning ScanMaxTimeSeconds read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningScanMaxTimeSeconds : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningScanMaxTimeSeconds()
        : SubscribeAttribute("scan-max-time-seconds")
    {
    }

    ~SubscribeAttributeNetworkCommissioningScanMaxTimeSeconds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeScanMaxTimeSecondsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.ScanMaxTimeSeconds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ConnectMaxTimeSeconds
 */
class ReadNetworkCommissioningConnectMaxTimeSeconds : public ReadAttribute {
public:
    ReadNetworkCommissioningConnectMaxTimeSeconds()
        : ReadAttribute("connect-max-time-seconds")
    {
    }

    ~ReadNetworkCommissioningConnectMaxTimeSeconds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeConnectMaxTimeSecondsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.ConnectMaxTimeSeconds response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning ConnectMaxTimeSeconds read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningConnectMaxTimeSeconds : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningConnectMaxTimeSeconds()
        : SubscribeAttribute("connect-max-time-seconds")
    {
    }

    ~SubscribeAttributeNetworkCommissioningConnectMaxTimeSeconds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeConnectMaxTimeSecondsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.ConnectMaxTimeSeconds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InterfaceEnabled
 */
class ReadNetworkCommissioningInterfaceEnabled : public ReadAttribute {
public:
    ReadNetworkCommissioningInterfaceEnabled()
        : ReadAttribute("interface-enabled")
    {
    }

    ~ReadNetworkCommissioningInterfaceEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeInterfaceEnabledWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.InterfaceEnabled response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning InterfaceEnabled read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteNetworkCommissioningInterfaceEnabled : public WriteAttribute {
public:
    WriteNetworkCommissioningInterfaceEnabled()
        : WriteAttribute("interface-enabled")
    {
        AddArgument("attr-name", "interface-enabled");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteNetworkCommissioningInterfaceEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeInterfaceEnabledWithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("NetworkCommissioning InterfaceEnabled write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeNetworkCommissioningInterfaceEnabled : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningInterfaceEnabled()
        : SubscribeAttribute("interface-enabled")
    {
    }

    ~SubscribeAttributeNetworkCommissioningInterfaceEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInterfaceEnabledWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.InterfaceEnabled response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LastNetworkingStatus
 */
class ReadNetworkCommissioningLastNetworkingStatus : public ReadAttribute {
public:
    ReadNetworkCommissioningLastNetworkingStatus()
        : ReadAttribute("last-networking-status")
    {
    }

    ~ReadNetworkCommissioningLastNetworkingStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLastNetworkingStatusWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.LastNetworkingStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning LastNetworkingStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningLastNetworkingStatus : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningLastNetworkingStatus()
        : SubscribeAttribute("last-networking-status")
    {
    }

    ~SubscribeAttributeNetworkCommissioningLastNetworkingStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLastNetworkingStatusWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.LastNetworkingStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LastNetworkID
 */
class ReadNetworkCommissioningLastNetworkID : public ReadAttribute {
public:
    ReadNetworkCommissioningLastNetworkID()
        : ReadAttribute("last-network-id")
    {
    }

    ~ReadNetworkCommissioningLastNetworkID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLastNetworkIDWithCompletionHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.LastNetworkID response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning LastNetworkID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningLastNetworkID : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningLastNetworkID()
        : SubscribeAttribute("last-network-id")
    {
    }

    ~SubscribeAttributeNetworkCommissioningLastNetworkID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLastNetworkIDWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.LastNetworkID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LastConnectErrorValue
 */
class ReadNetworkCommissioningLastConnectErrorValue : public ReadAttribute {
public:
    ReadNetworkCommissioningLastConnectErrorValue()
        : ReadAttribute("last-connect-error-value")
    {
    }

    ~ReadNetworkCommissioningLastConnectErrorValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLastConnectErrorValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.LastConnectErrorValue response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning LastConnectErrorValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningLastConnectErrorValue : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningLastConnectErrorValue()
        : SubscribeAttribute("last-connect-error-value")
    {
    }

    ~SubscribeAttributeNetworkCommissioningLastConnectErrorValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLastConnectErrorValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.LastConnectErrorValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadNetworkCommissioningGeneratedCommandList : public ReadAttribute {
public:
    ReadNetworkCommissioningGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadNetworkCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeNetworkCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadNetworkCommissioningAcceptedCommandList : public ReadAttribute {
public:
    ReadNetworkCommissioningAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadNetworkCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeNetworkCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadNetworkCommissioningAttributeList : public ReadAttribute {
public:
    ReadNetworkCommissioningAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadNetworkCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeNetworkCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadNetworkCommissioningFeatureMap : public ReadAttribute {
public:
    ReadNetworkCommissioningFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadNetworkCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeNetworkCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadNetworkCommissioningClusterRevision : public ReadAttribute {
public:
    ReadNetworkCommissioningClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadNetworkCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeNetworkCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster DiagnosticLogs                                              | 0x0032 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * RetrieveLogsRequest                                               |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command RetrieveLogsRequest
 */
class DiagnosticLogsRetrieveLogsRequest : public ClusterCommand {
public:
    DiagnosticLogsRetrieveLogsRequest()
        : ClusterCommand("retrieve-logs-request")
    {
        AddArgument("Intent", 0, UINT8_MAX, &mRequest.intent);
        AddArgument("RequestedProtocol", 0, UINT8_MAX, &mRequest.requestedProtocol);
        AddArgument("TransferFileDesignator", &mRequest.transferFileDesignator);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRDiagnosticLogsClusterRetrieveLogsRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.intent = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.intent)];
        params.requestedProtocol = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.requestedProtocol)];
        params.transferFileDesignator = [NSData dataWithBytes:mRequest.transferFileDesignator.data()
                                                       length:mRequest.transferFileDesignator.size()];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster retrieveLogsRequestWithParams:params
                                 completionHandler:^(MTRDiagnosticLogsClusterRetrieveLogsResponseParams * _Nullable values,
                                     NSError * _Nullable error) {
                                     NSLog(@"Values: %@", values);
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DiagnosticLogs::Commands::RetrieveLogsRequest::Type mRequest;
};

/*
 * Attribute GeneratedCommandList
 */
class ReadDiagnosticLogsGeneratedCommandList : public ReadAttribute {
public:
    ReadDiagnosticLogsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadDiagnosticLogsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DiagnosticLogs.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("DiagnosticLogs GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDiagnosticLogsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeDiagnosticLogsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadDiagnosticLogsAcceptedCommandList : public ReadAttribute {
public:
    ReadDiagnosticLogsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadDiagnosticLogsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DiagnosticLogs.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("DiagnosticLogs AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDiagnosticLogsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeDiagnosticLogsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadDiagnosticLogsAttributeList : public ReadAttribute {
public:
    ReadDiagnosticLogsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadDiagnosticLogsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DiagnosticLogs.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("DiagnosticLogs AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDiagnosticLogsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeDiagnosticLogsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadDiagnosticLogsFeatureMap : public ReadAttribute {
public:
    ReadDiagnosticLogsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadDiagnosticLogsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DiagnosticLogs.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("DiagnosticLogs FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDiagnosticLogsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeDiagnosticLogsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadDiagnosticLogsClusterRevision : public ReadAttribute {
public:
    ReadDiagnosticLogsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadDiagnosticLogsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DiagnosticLogs.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("DiagnosticLogs ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDiagnosticLogsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeDiagnosticLogsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster GeneralDiagnostics                                          | 0x0033 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * TestEventTrigger                                                  |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * NetworkInterfaces                                                 | 0x0000 |
| * RebootCount                                                       | 0x0001 |
| * UpTime                                                            | 0x0002 |
| * TotalOperationalHours                                             | 0x0003 |
| * BootReasons                                                       | 0x0004 |
| * ActiveHardwareFaults                                              | 0x0005 |
| * ActiveRadioFaults                                                 | 0x0006 |
| * ActiveNetworkFaults                                               | 0x0007 |
| * TestEventTriggersEnabled                                          | 0x0008 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * HardwareFaultChange                                               | 0x0000 |
| * RadioFaultChange                                                  | 0x0001 |
| * NetworkFaultChange                                                | 0x0002 |
| * BootReason                                                        | 0x0003 |
\*----------------------------------------------------------------------------*/

/*
 * Command TestEventTrigger
 */
class GeneralDiagnosticsTestEventTrigger : public ClusterCommand {
public:
    GeneralDiagnosticsTestEventTrigger()
        : ClusterCommand("test-event-trigger")
    {
        AddArgument("EnableKey", &mRequest.enableKey);
        AddArgument("EventTrigger", 0, UINT64_MAX, &mRequest.eventTrigger);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint: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
                              completionHandler:^(NSError * _Nullable error) {
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GeneralDiagnostics::Commands::TestEventTrigger::Type mRequest;
};

/*
 * Attribute NetworkInterfaces
 */
class ReadGeneralDiagnosticsNetworkInterfaces : public ReadAttribute {
public:
    ReadGeneralDiagnosticsNetworkInterfaces()
        : ReadAttribute("network-interfaces")
    {
    }

    ~ReadGeneralDiagnosticsNetworkInterfaces() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeNetworkInterfacesWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.NetworkInterfaces response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics NetworkInterfaces read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsNetworkInterfaces : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsNetworkInterfaces()
        : SubscribeAttribute("network-interfaces")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsNetworkInterfaces() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNetworkInterfacesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.NetworkInterfaces response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RebootCount
 */
class ReadGeneralDiagnosticsRebootCount : public ReadAttribute {
public:
    ReadGeneralDiagnosticsRebootCount()
        : ReadAttribute("reboot-count")
    {
    }

    ~ReadGeneralDiagnosticsRebootCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeRebootCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.RebootCount response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics RebootCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsRebootCount : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsRebootCount()
        : SubscribeAttribute("reboot-count")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsRebootCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRebootCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.RebootCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UpTime
 */
class ReadGeneralDiagnosticsUpTime : public ReadAttribute {
public:
    ReadGeneralDiagnosticsUpTime()
        : ReadAttribute("up-time")
    {
    }

    ~ReadGeneralDiagnosticsUpTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeUpTimeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.UpTime response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics UpTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsUpTime : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsUpTime()
        : SubscribeAttribute("up-time")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsUpTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUpTimeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.UpTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TotalOperationalHours
 */
class ReadGeneralDiagnosticsTotalOperationalHours : public ReadAttribute {
public:
    ReadGeneralDiagnosticsTotalOperationalHours()
        : ReadAttribute("total-operational-hours")
    {
    }

    ~ReadGeneralDiagnosticsTotalOperationalHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeTotalOperationalHoursWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.TotalOperationalHours response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics TotalOperationalHours read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsTotalOperationalHours : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsTotalOperationalHours()
        : SubscribeAttribute("total-operational-hours")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsTotalOperationalHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTotalOperationalHoursWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.TotalOperationalHours response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BootReasons
 */
class ReadGeneralDiagnosticsBootReasons : public ReadAttribute {
public:
    ReadGeneralDiagnosticsBootReasons()
        : ReadAttribute("boot-reasons")
    {
    }

    ~ReadGeneralDiagnosticsBootReasons() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeBootReasonsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.BootReasons response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics BootReasons read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsBootReasons : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsBootReasons()
        : SubscribeAttribute("boot-reasons")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsBootReasons() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBootReasonsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.BootReasons response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveHardwareFaults
 */
class ReadGeneralDiagnosticsActiveHardwareFaults : public ReadAttribute {
public:
    ReadGeneralDiagnosticsActiveHardwareFaults()
        : ReadAttribute("active-hardware-faults")
    {
    }

    ~ReadGeneralDiagnosticsActiveHardwareFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeActiveHardwareFaultsWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.ActiveHardwareFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics ActiveHardwareFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsActiveHardwareFaults : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsActiveHardwareFaults()
        : SubscribeAttribute("active-hardware-faults")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsActiveHardwareFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveHardwareFaultsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.ActiveHardwareFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveRadioFaults
 */
class ReadGeneralDiagnosticsActiveRadioFaults : public ReadAttribute {
public:
    ReadGeneralDiagnosticsActiveRadioFaults()
        : ReadAttribute("active-radio-faults")
    {
    }

    ~ReadGeneralDiagnosticsActiveRadioFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeActiveRadioFaultsWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.ActiveRadioFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics ActiveRadioFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsActiveRadioFaults : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsActiveRadioFaults()
        : SubscribeAttribute("active-radio-faults")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsActiveRadioFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveRadioFaultsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.ActiveRadioFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveNetworkFaults
 */
class ReadGeneralDiagnosticsActiveNetworkFaults : public ReadAttribute {
public:
    ReadGeneralDiagnosticsActiveNetworkFaults()
        : ReadAttribute("active-network-faults")
    {
    }

    ~ReadGeneralDiagnosticsActiveNetworkFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeActiveNetworkFaultsWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.ActiveNetworkFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics ActiveNetworkFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsActiveNetworkFaults : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsActiveNetworkFaults()
        : SubscribeAttribute("active-network-faults")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsActiveNetworkFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveNetworkFaultsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.ActiveNetworkFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TestEventTriggersEnabled
 */
class ReadGeneralDiagnosticsTestEventTriggersEnabled : public ReadAttribute {
public:
    ReadGeneralDiagnosticsTestEventTriggersEnabled()
        : ReadAttribute("test-event-triggers-enabled")
    {
    }

    ~ReadGeneralDiagnosticsTestEventTriggersEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster
            readAttributeTestEventTriggersEnabledWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.TestEventTriggersEnabled response %@", [value description]);
                if (error != nil) {
                    LogNSError("GeneralDiagnostics TestEventTriggersEnabled read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsTestEventTriggersEnabled : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsTestEventTriggersEnabled()
        : SubscribeAttribute("test-event-triggers-enabled")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsTestEventTriggersEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTestEventTriggersEnabledWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.TestEventTriggersEnabled response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadGeneralDiagnosticsGeneratedCommandList : public ReadAttribute {
public:
    ReadGeneralDiagnosticsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadGeneralDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadGeneralDiagnosticsAcceptedCommandList : public ReadAttribute {
public:
    ReadGeneralDiagnosticsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadGeneralDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadGeneralDiagnosticsAttributeList : public ReadAttribute {
public:
    ReadGeneralDiagnosticsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadGeneralDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadGeneralDiagnosticsFeatureMap : public ReadAttribute {
public:
    ReadGeneralDiagnosticsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadGeneralDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadGeneralDiagnosticsClusterRevision : public ReadAttribute {
public:
    ReadGeneralDiagnosticsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadGeneralDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster SoftwareDiagnostics                                         | 0x0034 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetWatermarks                                                   |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * ThreadMetrics                                                     | 0x0000 |
| * CurrentHeapFree                                                   | 0x0001 |
| * CurrentHeapUsed                                                   | 0x0002 |
| * CurrentHeapHighWatermark                                          | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * SoftwareFault                                                     | 0x0000 |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetWatermarks
 */
class SoftwareDiagnosticsResetWatermarks : public ClusterCommand {
public:
    SoftwareDiagnosticsResetWatermarks()
        : ClusterCommand("reset-watermarks")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint: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
                             completionHandler:^(NSError * _Nullable error) {
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute ThreadMetrics
 */
class ReadSoftwareDiagnosticsThreadMetrics : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsThreadMetrics()
        : ReadAttribute("thread-metrics")
    {
    }

    ~ReadSoftwareDiagnosticsThreadMetrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeThreadMetricsWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.ThreadMetrics response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics ThreadMetrics read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsThreadMetrics : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsThreadMetrics()
        : SubscribeAttribute("thread-metrics")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsThreadMetrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeThreadMetricsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.ThreadMetrics response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentHeapFree
 */
class ReadSoftwareDiagnosticsCurrentHeapFree : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsCurrentHeapFree()
        : ReadAttribute("current-heap-free")
    {
    }

    ~ReadSoftwareDiagnosticsCurrentHeapFree() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeCurrentHeapFreeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.CurrentHeapFree response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics CurrentHeapFree read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsCurrentHeapFree : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsCurrentHeapFree()
        : SubscribeAttribute("current-heap-free")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsCurrentHeapFree() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentHeapFreeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.CurrentHeapFree response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentHeapUsed
 */
class ReadSoftwareDiagnosticsCurrentHeapUsed : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsCurrentHeapUsed()
        : ReadAttribute("current-heap-used")
    {
    }

    ~ReadSoftwareDiagnosticsCurrentHeapUsed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeCurrentHeapUsedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.CurrentHeapUsed response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics CurrentHeapUsed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsCurrentHeapUsed : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsCurrentHeapUsed()
        : SubscribeAttribute("current-heap-used")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsCurrentHeapUsed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentHeapUsedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.CurrentHeapUsed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentHeapHighWatermark
 */
class ReadSoftwareDiagnosticsCurrentHeapHighWatermark : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsCurrentHeapHighWatermark()
        : ReadAttribute("current-heap-high-watermark")
    {
    }

    ~ReadSoftwareDiagnosticsCurrentHeapHighWatermark() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster
            readAttributeCurrentHeapHighWatermarkWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.CurrentHeapHighWatermark response %@", [value description]);
                if (error != nil) {
                    LogNSError("SoftwareDiagnostics CurrentHeapHighWatermark read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsCurrentHeapHighWatermark : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsCurrentHeapHighWatermark()
        : SubscribeAttribute("current-heap-high-watermark")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsCurrentHeapHighWatermark() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentHeapHighWatermarkWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.CurrentHeapHighWatermark response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadSoftwareDiagnosticsGeneratedCommandList : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadSoftwareDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadSoftwareDiagnosticsAcceptedCommandList : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadSoftwareDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadSoftwareDiagnosticsAttributeList : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadSoftwareDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadSoftwareDiagnosticsFeatureMap : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadSoftwareDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadSoftwareDiagnosticsClusterRevision : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadSoftwareDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ThreadNetworkDiagnostics                                    | 0x0035 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCounts                                                       |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Channel                                                           | 0x0000 |
| * RoutingRole                                                       | 0x0001 |
| * NetworkName                                                       | 0x0002 |
| * PanId                                                             | 0x0003 |
| * ExtendedPanId                                                     | 0x0004 |
| * MeshLocalPrefix                                                   | 0x0005 |
| * OverrunCount                                                      | 0x0006 |
| * NeighborTableList                                                 | 0x0007 |
| * RouteTableList                                                    | 0x0008 |
| * PartitionId                                                       | 0x0009 |
| * Weighting                                                         | 0x000A |
| * DataVersion                                                       | 0x000B |
| * StableDataVersion                                                 | 0x000C |
| * LeaderRouterId                                                    | 0x000D |
| * DetachedRoleCount                                                 | 0x000E |
| * ChildRoleCount                                                    | 0x000F |
| * RouterRoleCount                                                   | 0x0010 |
| * LeaderRoleCount                                                   | 0x0011 |
| * AttachAttemptCount                                                | 0x0012 |
| * PartitionIdChangeCount                                            | 0x0013 |
| * BetterPartitionAttachAttemptCount                                 | 0x0014 |
| * ParentChangeCount                                                 | 0x0015 |
| * TxTotalCount                                                      | 0x0016 |
| * TxUnicastCount                                                    | 0x0017 |
| * TxBroadcastCount                                                  | 0x0018 |
| * TxAckRequestedCount                                               | 0x0019 |
| * TxAckedCount                                                      | 0x001A |
| * TxNoAckRequestedCount                                             | 0x001B |
| * TxDataCount                                                       | 0x001C |
| * TxDataPollCount                                                   | 0x001D |
| * TxBeaconCount                                                     | 0x001E |
| * TxBeaconRequestCount                                              | 0x001F |
| * TxOtherCount                                                      | 0x0020 |
| * TxRetryCount                                                      | 0x0021 |
| * TxDirectMaxRetryExpiryCount                                       | 0x0022 |
| * TxIndirectMaxRetryExpiryCount                                     | 0x0023 |
| * TxErrCcaCount                                                     | 0x0024 |
| * TxErrAbortCount                                                   | 0x0025 |
| * TxErrBusyChannelCount                                             | 0x0026 |
| * RxTotalCount                                                      | 0x0027 |
| * RxUnicastCount                                                    | 0x0028 |
| * RxBroadcastCount                                                  | 0x0029 |
| * RxDataCount                                                       | 0x002A |
| * RxDataPollCount                                                   | 0x002B |
| * RxBeaconCount                                                     | 0x002C |
| * RxBeaconRequestCount                                              | 0x002D |
| * RxOtherCount                                                      | 0x002E |
| * RxAddressFilteredCount                                            | 0x002F |
| * RxDestAddrFilteredCount                                           | 0x0030 |
| * RxDuplicatedCount                                                 | 0x0031 |
| * RxErrNoFrameCount                                                 | 0x0032 |
| * RxErrUnknownNeighborCount                                         | 0x0033 |
| * RxErrInvalidSrcAddrCount                                          | 0x0034 |
| * RxErrSecCount                                                     | 0x0035 |
| * RxErrFcsCount                                                     | 0x0036 |
| * RxErrOtherCount                                                   | 0x0037 |
| * ActiveTimestamp                                                   | 0x0038 |
| * PendingTimestamp                                                  | 0x0039 |
| * Delay                                                             | 0x003A |
| * SecurityPolicy                                                    | 0x003B |
| * ChannelMask                                                       | 0x003C |
| * OperationalDatasetComponents                                      | 0x003D |
| * ActiveNetworkFaultsList                                           | 0x003E |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * ConnectionStatus                                                  | 0x0000 |
| * NetworkFaultChange                                                | 0x0001 |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCounts
 */
class ThreadNetworkDiagnosticsResetCounts : public ClusterCommand {
public:
    ThreadNetworkDiagnosticsResetCounts()
        : ClusterCommand("reset-counts")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint: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
                         completionHandler:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute Channel
 */
class ReadThreadNetworkDiagnosticsChannel : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsChannel()
        : ReadAttribute("channel")
    {
    }

    ~ReadThreadNetworkDiagnosticsChannel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeChannelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.Channel response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics Channel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsChannel : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsChannel()
        : SubscribeAttribute("channel")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsChannel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeChannelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.Channel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RoutingRole
 */
class ReadThreadNetworkDiagnosticsRoutingRole : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRoutingRole()
        : ReadAttribute("routing-role")
    {
    }

    ~ReadThreadNetworkDiagnosticsRoutingRole() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRoutingRoleWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RoutingRole response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RoutingRole read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRoutingRole : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRoutingRole()
        : SubscribeAttribute("routing-role")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRoutingRole() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRoutingRoleWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RoutingRole response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NetworkName
 */
class ReadThreadNetworkDiagnosticsNetworkName : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsNetworkName()
        : ReadAttribute("network-name")
    {
    }

    ~ReadThreadNetworkDiagnosticsNetworkName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeNetworkNameWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.NetworkName response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics NetworkName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsNetworkName : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsNetworkName()
        : SubscribeAttribute("network-name")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsNetworkName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNetworkNameWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.NetworkName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PanId
 */
class ReadThreadNetworkDiagnosticsPanId : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsPanId()
        : ReadAttribute("pan-id")
    {
    }

    ~ReadThreadNetworkDiagnosticsPanId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePanIdWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.PanId response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics PanId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsPanId : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsPanId()
        : SubscribeAttribute("pan-id")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsPanId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePanIdWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.PanId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ExtendedPanId
 */
class ReadThreadNetworkDiagnosticsExtendedPanId : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsExtendedPanId()
        : ReadAttribute("extended-pan-id")
    {
    }

    ~ReadThreadNetworkDiagnosticsExtendedPanId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeExtendedPanIdWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ExtendedPanId response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ExtendedPanId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsExtendedPanId : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsExtendedPanId()
        : SubscribeAttribute("extended-pan-id")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsExtendedPanId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeExtendedPanIdWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ExtendedPanId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeshLocalPrefix
 */
class ReadThreadNetworkDiagnosticsMeshLocalPrefix : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsMeshLocalPrefix()
        : ReadAttribute("mesh-local-prefix")
    {
    }

    ~ReadThreadNetworkDiagnosticsMeshLocalPrefix() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMeshLocalPrefixWithCompletionHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.MeshLocalPrefix response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics MeshLocalPrefix read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsMeshLocalPrefix : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsMeshLocalPrefix()
        : SubscribeAttribute("mesh-local-prefix")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsMeshLocalPrefix() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeshLocalPrefixWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.MeshLocalPrefix response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OverrunCount
 */
class ReadThreadNetworkDiagnosticsOverrunCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsOverrunCount()
        : ReadAttribute("overrun-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeOverrunCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.OverrunCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics OverrunCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsOverrunCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsOverrunCount()
        : SubscribeAttribute("overrun-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOverrunCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.OverrunCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NeighborTableList
 */
class ReadThreadNetworkDiagnosticsNeighborTableList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsNeighborTableList()
        : ReadAttribute("neighbor-table-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsNeighborTableList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeNeighborTableListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.NeighborTableList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics NeighborTableList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsNeighborTableList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsNeighborTableList()
        : SubscribeAttribute("neighbor-table-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsNeighborTableList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNeighborTableListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.NeighborTableList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RouteTableList
 */
class ReadThreadNetworkDiagnosticsRouteTableList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRouteTableList()
        : ReadAttribute("route-table-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsRouteTableList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRouteTableListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RouteTableList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RouteTableList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRouteTableList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRouteTableList()
        : SubscribeAttribute("route-table-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRouteTableList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRouteTableListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RouteTableList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PartitionId
 */
class ReadThreadNetworkDiagnosticsPartitionId : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsPartitionId()
        : ReadAttribute("partition-id")
    {
    }

    ~ReadThreadNetworkDiagnosticsPartitionId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePartitionIdWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.PartitionId response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics PartitionId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsPartitionId : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsPartitionId()
        : SubscribeAttribute("partition-id")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsPartitionId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePartitionIdWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.PartitionId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Weighting
 */
class ReadThreadNetworkDiagnosticsWeighting : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsWeighting()
        : ReadAttribute("weighting")
    {
    }

    ~ReadThreadNetworkDiagnosticsWeighting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeWeightingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.Weighting response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics Weighting read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsWeighting : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsWeighting()
        : SubscribeAttribute("weighting")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsWeighting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWeightingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.Weighting response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DataVersion
 */
class ReadThreadNetworkDiagnosticsDataVersion : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsDataVersion()
        : ReadAttribute("data-version")
    {
    }

    ~ReadThreadNetworkDiagnosticsDataVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeDataVersionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.DataVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics DataVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsDataVersion : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsDataVersion()
        : SubscribeAttribute("data-version")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsDataVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDataVersionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.DataVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StableDataVersion
 */
class ReadThreadNetworkDiagnosticsStableDataVersion : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsStableDataVersion()
        : ReadAttribute("stable-data-version")
    {
    }

    ~ReadThreadNetworkDiagnosticsStableDataVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeStableDataVersionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.StableDataVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics StableDataVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsStableDataVersion : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsStableDataVersion()
        : SubscribeAttribute("stable-data-version")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsStableDataVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeStableDataVersionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.StableDataVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LeaderRouterId
 */
class ReadThreadNetworkDiagnosticsLeaderRouterId : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsLeaderRouterId()
        : ReadAttribute("leader-router-id")
    {
    }

    ~ReadThreadNetworkDiagnosticsLeaderRouterId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeLeaderRouterIdWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.LeaderRouterId response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics LeaderRouterId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsLeaderRouterId : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsLeaderRouterId()
        : SubscribeAttribute("leader-router-id")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsLeaderRouterId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLeaderRouterIdWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.LeaderRouterId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DetachedRoleCount
 */
class ReadThreadNetworkDiagnosticsDetachedRoleCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsDetachedRoleCount()
        : ReadAttribute("detached-role-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsDetachedRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeDetachedRoleCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.DetachedRoleCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics DetachedRoleCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsDetachedRoleCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsDetachedRoleCount()
        : SubscribeAttribute("detached-role-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsDetachedRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDetachedRoleCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.DetachedRoleCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChildRoleCount
 */
class ReadThreadNetworkDiagnosticsChildRoleCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsChildRoleCount()
        : ReadAttribute("child-role-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsChildRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeChildRoleCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ChildRoleCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ChildRoleCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsChildRoleCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsChildRoleCount()
        : SubscribeAttribute("child-role-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsChildRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeChildRoleCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ChildRoleCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RouterRoleCount
 */
class ReadThreadNetworkDiagnosticsRouterRoleCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRouterRoleCount()
        : ReadAttribute("router-role-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRouterRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRouterRoleCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RouterRoleCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RouterRoleCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRouterRoleCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRouterRoleCount()
        : SubscribeAttribute("router-role-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRouterRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRouterRoleCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RouterRoleCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LeaderRoleCount
 */
class ReadThreadNetworkDiagnosticsLeaderRoleCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsLeaderRoleCount()
        : ReadAttribute("leader-role-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsLeaderRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeLeaderRoleCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.LeaderRoleCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics LeaderRoleCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsLeaderRoleCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsLeaderRoleCount()
        : SubscribeAttribute("leader-role-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsLeaderRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLeaderRoleCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.LeaderRoleCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttachAttemptCount
 */
class ReadThreadNetworkDiagnosticsAttachAttemptCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsAttachAttemptCount()
        : ReadAttribute("attach-attempt-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsAttachAttemptCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttachAttemptCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.AttachAttemptCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics AttachAttemptCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsAttachAttemptCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsAttachAttemptCount()
        : SubscribeAttribute("attach-attempt-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsAttachAttemptCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttachAttemptCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.AttachAttemptCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PartitionIdChangeCount
 */
class ReadThreadNetworkDiagnosticsPartitionIdChangeCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsPartitionIdChangeCount()
        : ReadAttribute("partition-id-change-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsPartitionIdChangeCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePartitionIdChangeCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.PartitionIdChangeCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics PartitionIdChangeCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsPartitionIdChangeCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsPartitionIdChangeCount()
        : SubscribeAttribute("partition-id-change-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsPartitionIdChangeCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePartitionIdChangeCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.PartitionIdChangeCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BetterPartitionAttachAttemptCount
 */
class ReadThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount()
        : ReadAttribute("better-partition-attach-attempt-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeBetterPartitionAttachAttemptCountWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.BetterPartitionAttachAttemptCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics BetterPartitionAttachAttemptCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount()
        : SubscribeAttribute("better-partition-attach-attempt-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBetterPartitionAttachAttemptCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.BetterPartitionAttachAttemptCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ParentChangeCount
 */
class ReadThreadNetworkDiagnosticsParentChangeCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsParentChangeCount()
        : ReadAttribute("parent-change-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsParentChangeCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeParentChangeCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ParentChangeCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ParentChangeCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsParentChangeCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsParentChangeCount()
        : SubscribeAttribute("parent-change-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsParentChangeCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeParentChangeCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ParentChangeCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxTotalCount
 */
class ReadThreadNetworkDiagnosticsTxTotalCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxTotalCount()
        : ReadAttribute("tx-total-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxTotalCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxTotalCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxTotalCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxTotalCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxTotalCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxTotalCount()
        : SubscribeAttribute("tx-total-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxTotalCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxTotalCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxTotalCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxUnicastCount
 */
class ReadThreadNetworkDiagnosticsTxUnicastCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxUnicastCount()
        : ReadAttribute("tx-unicast-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxUnicastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxUnicastCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxUnicastCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxUnicastCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxUnicastCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxUnicastCount()
        : SubscribeAttribute("tx-unicast-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxUnicastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxUnicastCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxUnicastCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxBroadcastCount
 */
class ReadThreadNetworkDiagnosticsTxBroadcastCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxBroadcastCount()
        : ReadAttribute("tx-broadcast-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxBroadcastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxBroadcastCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxBroadcastCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxBroadcastCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxBroadcastCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxBroadcastCount()
        : SubscribeAttribute("tx-broadcast-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxBroadcastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxBroadcastCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxBroadcastCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxAckRequestedCount
 */
class ReadThreadNetworkDiagnosticsTxAckRequestedCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxAckRequestedCount()
        : ReadAttribute("tx-ack-requested-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxAckRequestedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxAckRequestedCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxAckRequestedCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxAckRequestedCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxAckRequestedCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxAckRequestedCount()
        : SubscribeAttribute("tx-ack-requested-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxAckRequestedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxAckRequestedCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxAckRequestedCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxAckedCount
 */
class ReadThreadNetworkDiagnosticsTxAckedCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxAckedCount()
        : ReadAttribute("tx-acked-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxAckedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxAckedCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxAckedCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxAckedCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxAckedCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxAckedCount()
        : SubscribeAttribute("tx-acked-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxAckedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxAckedCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxAckedCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxNoAckRequestedCount
 */
class ReadThreadNetworkDiagnosticsTxNoAckRequestedCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxNoAckRequestedCount()
        : ReadAttribute("tx-no-ack-requested-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxNoAckRequestedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxNoAckRequestedCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxNoAckRequestedCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxNoAckRequestedCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxNoAckRequestedCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxNoAckRequestedCount()
        : SubscribeAttribute("tx-no-ack-requested-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxNoAckRequestedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxNoAckRequestedCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxNoAckRequestedCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxDataCount
 */
class ReadThreadNetworkDiagnosticsTxDataCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxDataCount()
        : ReadAttribute("tx-data-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxDataCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxDataCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxDataCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxDataCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxDataCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxDataCount()
        : SubscribeAttribute("tx-data-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxDataCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxDataCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxDataCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxDataPollCount
 */
class ReadThreadNetworkDiagnosticsTxDataPollCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxDataPollCount()
        : ReadAttribute("tx-data-poll-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxDataPollCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxDataPollCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxDataPollCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxDataPollCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxDataPollCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxDataPollCount()
        : SubscribeAttribute("tx-data-poll-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxDataPollCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxDataPollCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxDataPollCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxBeaconCount
 */
class ReadThreadNetworkDiagnosticsTxBeaconCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxBeaconCount()
        : ReadAttribute("tx-beacon-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxBeaconCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxBeaconCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxBeaconCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxBeaconCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxBeaconCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxBeaconCount()
        : SubscribeAttribute("tx-beacon-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxBeaconCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxBeaconCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxBeaconCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxBeaconRequestCount
 */
class ReadThreadNetworkDiagnosticsTxBeaconRequestCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxBeaconRequestCount()
        : ReadAttribute("tx-beacon-request-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxBeaconRequestCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxBeaconRequestCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxBeaconRequestCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxBeaconRequestCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxBeaconRequestCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxBeaconRequestCount()
        : SubscribeAttribute("tx-beacon-request-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxBeaconRequestCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxBeaconRequestCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxBeaconRequestCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxOtherCount
 */
class ReadThreadNetworkDiagnosticsTxOtherCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxOtherCount()
        : ReadAttribute("tx-other-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxOtherCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxOtherCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxOtherCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxOtherCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxOtherCount()
        : SubscribeAttribute("tx-other-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxOtherCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxOtherCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxRetryCount
 */
class ReadThreadNetworkDiagnosticsTxRetryCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxRetryCount()
        : ReadAttribute("tx-retry-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxRetryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxRetryCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxRetryCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxRetryCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxRetryCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxRetryCount()
        : SubscribeAttribute("tx-retry-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxRetryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxRetryCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxRetryCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxDirectMaxRetryExpiryCount
 */
class ReadThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount()
        : ReadAttribute("tx-direct-max-retry-expiry-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster
            readAttributeTxDirectMaxRetryExpiryCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxDirectMaxRetryExpiryCount response %@", [value description]);
                if (error != nil) {
                    LogNSError("ThreadNetworkDiagnostics TxDirectMaxRetryExpiryCount read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount()
        : SubscribeAttribute("tx-direct-max-retry-expiry-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxDirectMaxRetryExpiryCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxDirectMaxRetryExpiryCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxIndirectMaxRetryExpiryCount
 */
class ReadThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount()
        : ReadAttribute("tx-indirect-max-retry-expiry-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000023) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxIndirectMaxRetryExpiryCountWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxIndirectMaxRetryExpiryCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxIndirectMaxRetryExpiryCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount()
        : SubscribeAttribute("tx-indirect-max-retry-expiry-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxIndirectMaxRetryExpiryCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxIndirectMaxRetryExpiryCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxErrCcaCount
 */
class ReadThreadNetworkDiagnosticsTxErrCcaCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxErrCcaCount()
        : ReadAttribute("tx-err-cca-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxErrCcaCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxErrCcaCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxErrCcaCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxErrCcaCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxErrCcaCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxErrCcaCount()
        : SubscribeAttribute("tx-err-cca-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxErrCcaCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxErrCcaCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxErrCcaCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxErrAbortCount
 */
class ReadThreadNetworkDiagnosticsTxErrAbortCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxErrAbortCount()
        : ReadAttribute("tx-err-abort-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxErrAbortCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxErrAbortCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxErrAbortCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxErrAbortCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxErrAbortCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxErrAbortCount()
        : SubscribeAttribute("tx-err-abort-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxErrAbortCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxErrAbortCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxErrAbortCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxErrBusyChannelCount
 */
class ReadThreadNetworkDiagnosticsTxErrBusyChannelCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxErrBusyChannelCount()
        : ReadAttribute("tx-err-busy-channel-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxErrBusyChannelCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxErrBusyChannelCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxErrBusyChannelCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxErrBusyChannelCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxErrBusyChannelCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxErrBusyChannelCount()
        : SubscribeAttribute("tx-err-busy-channel-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxErrBusyChannelCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxErrBusyChannelCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxErrBusyChannelCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxTotalCount
 */
class ReadThreadNetworkDiagnosticsRxTotalCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxTotalCount()
        : ReadAttribute("rx-total-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxTotalCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000027) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxTotalCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxTotalCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxTotalCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxTotalCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxTotalCount()
        : SubscribeAttribute("rx-total-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxTotalCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxTotalCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxTotalCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxUnicastCount
 */
class ReadThreadNetworkDiagnosticsRxUnicastCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxUnicastCount()
        : ReadAttribute("rx-unicast-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxUnicastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000028) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxUnicastCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxUnicastCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxUnicastCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxUnicastCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxUnicastCount()
        : SubscribeAttribute("rx-unicast-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxUnicastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxUnicastCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxUnicastCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxBroadcastCount
 */
class ReadThreadNetworkDiagnosticsRxBroadcastCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxBroadcastCount()
        : ReadAttribute("rx-broadcast-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxBroadcastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxBroadcastCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxBroadcastCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxBroadcastCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxBroadcastCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxBroadcastCount()
        : SubscribeAttribute("rx-broadcast-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxBroadcastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxBroadcastCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxBroadcastCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxDataCount
 */
class ReadThreadNetworkDiagnosticsRxDataCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxDataCount()
        : ReadAttribute("rx-data-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxDataCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxDataCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxDataCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxDataCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxDataCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxDataCount()
        : SubscribeAttribute("rx-data-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxDataCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxDataCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxDataCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxDataPollCount
 */
class ReadThreadNetworkDiagnosticsRxDataPollCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxDataPollCount()
        : ReadAttribute("rx-data-poll-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxDataPollCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxDataPollCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxDataPollCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxDataPollCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxDataPollCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxDataPollCount()
        : SubscribeAttribute("rx-data-poll-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxDataPollCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxDataPollCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxDataPollCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxBeaconCount
 */
class ReadThreadNetworkDiagnosticsRxBeaconCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxBeaconCount()
        : ReadAttribute("rx-beacon-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxBeaconCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxBeaconCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxBeaconCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxBeaconCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxBeaconCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxBeaconCount()
        : SubscribeAttribute("rx-beacon-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxBeaconCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxBeaconCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxBeaconCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxBeaconRequestCount
 */
class ReadThreadNetworkDiagnosticsRxBeaconRequestCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxBeaconRequestCount()
        : ReadAttribute("rx-beacon-request-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxBeaconRequestCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxBeaconRequestCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxBeaconRequestCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxBeaconRequestCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxBeaconRequestCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxBeaconRequestCount()
        : SubscribeAttribute("rx-beacon-request-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxBeaconRequestCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxBeaconRequestCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxBeaconRequestCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxOtherCount
 */
class ReadThreadNetworkDiagnosticsRxOtherCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxOtherCount()
        : ReadAttribute("rx-other-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxOtherCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxOtherCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxOtherCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxOtherCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxOtherCount()
        : SubscribeAttribute("rx-other-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxOtherCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxOtherCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxAddressFilteredCount
 */
class ReadThreadNetworkDiagnosticsRxAddressFilteredCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxAddressFilteredCount()
        : ReadAttribute("rx-address-filtered-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxAddressFilteredCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxAddressFilteredCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxAddressFilteredCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxAddressFilteredCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxAddressFilteredCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxAddressFilteredCount()
        : SubscribeAttribute("rx-address-filtered-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxAddressFilteredCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxAddressFilteredCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxAddressFilteredCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxDestAddrFilteredCount
 */
class ReadThreadNetworkDiagnosticsRxDestAddrFilteredCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxDestAddrFilteredCount()
        : ReadAttribute("rx-dest-addr-filtered-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxDestAddrFilteredCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster
            readAttributeRxDestAddrFilteredCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxDestAddrFilteredCount response %@", [value description]);
                if (error != nil) {
                    LogNSError("ThreadNetworkDiagnostics RxDestAddrFilteredCount read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxDestAddrFilteredCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxDestAddrFilteredCount()
        : SubscribeAttribute("rx-dest-addr-filtered-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxDestAddrFilteredCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxDestAddrFilteredCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxDestAddrFilteredCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxDuplicatedCount
 */
class ReadThreadNetworkDiagnosticsRxDuplicatedCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxDuplicatedCount()
        : ReadAttribute("rx-duplicated-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxDuplicatedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxDuplicatedCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxDuplicatedCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxDuplicatedCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxDuplicatedCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxDuplicatedCount()
        : SubscribeAttribute("rx-duplicated-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxDuplicatedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxDuplicatedCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxDuplicatedCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrNoFrameCount
 */
class ReadThreadNetworkDiagnosticsRxErrNoFrameCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrNoFrameCount()
        : ReadAttribute("rx-err-no-frame-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrNoFrameCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxErrNoFrameCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxErrNoFrameCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxErrNoFrameCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrNoFrameCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrNoFrameCount()
        : SubscribeAttribute("rx-err-no-frame-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrNoFrameCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxErrNoFrameCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrNoFrameCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrUnknownNeighborCount
 */
class ReadThreadNetworkDiagnosticsRxErrUnknownNeighborCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrUnknownNeighborCount()
        : ReadAttribute("rx-err-unknown-neighbor-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrUnknownNeighborCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000033) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster
            readAttributeRxErrUnknownNeighborCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrUnknownNeighborCount response %@", [value description]);
                if (error != nil) {
                    LogNSError("ThreadNetworkDiagnostics RxErrUnknownNeighborCount read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrUnknownNeighborCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrUnknownNeighborCount()
        : SubscribeAttribute("rx-err-unknown-neighbor-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrUnknownNeighborCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxErrUnknownNeighborCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrUnknownNeighborCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrInvalidSrcAddrCount
 */
class ReadThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount()
        : ReadAttribute("rx-err-invalid-src-addr-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000034) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster
            readAttributeRxErrInvalidSrcAddrCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrInvalidSrcAddrCount response %@", [value description]);
                if (error != nil) {
                    LogNSError("ThreadNetworkDiagnostics RxErrInvalidSrcAddrCount read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount()
        : SubscribeAttribute("rx-err-invalid-src-addr-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxErrInvalidSrcAddrCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrInvalidSrcAddrCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrSecCount
 */
class ReadThreadNetworkDiagnosticsRxErrSecCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrSecCount()
        : ReadAttribute("rx-err-sec-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrSecCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000035) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxErrSecCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxErrSecCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxErrSecCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrSecCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrSecCount()
        : SubscribeAttribute("rx-err-sec-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrSecCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxErrSecCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrSecCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrFcsCount
 */
class ReadThreadNetworkDiagnosticsRxErrFcsCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrFcsCount()
        : ReadAttribute("rx-err-fcs-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrFcsCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000036) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxErrFcsCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxErrFcsCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxErrFcsCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrFcsCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrFcsCount()
        : SubscribeAttribute("rx-err-fcs-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrFcsCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000036) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxErrFcsCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrFcsCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrOtherCount
 */
class ReadThreadNetworkDiagnosticsRxErrOtherCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrOtherCount()
        : ReadAttribute("rx-err-other-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000037) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRxErrOtherCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxErrOtherCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxErrOtherCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrOtherCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrOtherCount()
        : SubscribeAttribute("rx-err-other-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000037) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRxErrOtherCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrOtherCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveTimestamp
 */
class ReadThreadNetworkDiagnosticsActiveTimestamp : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsActiveTimestamp()
        : ReadAttribute("active-timestamp")
    {
    }

    ~ReadThreadNetworkDiagnosticsActiveTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000038) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeActiveTimestampWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ActiveTimestamp response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ActiveTimestamp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsActiveTimestamp : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsActiveTimestamp()
        : SubscribeAttribute("active-timestamp")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsActiveTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000038) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveTimestampWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ActiveTimestamp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PendingTimestamp
 */
class ReadThreadNetworkDiagnosticsPendingTimestamp : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsPendingTimestamp()
        : ReadAttribute("pending-timestamp")
    {
    }

    ~ReadThreadNetworkDiagnosticsPendingTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000039) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePendingTimestampWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.PendingTimestamp response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics PendingTimestamp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsPendingTimestamp : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsPendingTimestamp()
        : SubscribeAttribute("pending-timestamp")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsPendingTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000039) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePendingTimestampWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.PendingTimestamp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Delay
 */
class ReadThreadNetworkDiagnosticsDelay : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsDelay()
        : ReadAttribute("delay")
    {
    }

    ~ReadThreadNetworkDiagnosticsDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000003A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeDelayWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.Delay response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics Delay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsDelay : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsDelay()
        : SubscribeAttribute("delay")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000003A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDelayWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.Delay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SecurityPolicy
 */
class ReadThreadNetworkDiagnosticsSecurityPolicy : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsSecurityPolicy()
        : ReadAttribute("security-policy")
    {
    }

    ~ReadThreadNetworkDiagnosticsSecurityPolicy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000003B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeSecurityPolicyWithCompletionHandler:^(
            MTRThreadNetworkDiagnosticsClusterSecurityPolicy * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.SecurityPolicy response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics SecurityPolicy read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsSecurityPolicy : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsSecurityPolicy()
        : SubscribeAttribute("security-policy")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsSecurityPolicy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000003B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSecurityPolicyWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRThreadNetworkDiagnosticsClusterSecurityPolicy * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.SecurityPolicy response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChannelMask
 */
class ReadThreadNetworkDiagnosticsChannelMask : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsChannelMask()
        : ReadAttribute("channel-mask")
    {
    }

    ~ReadThreadNetworkDiagnosticsChannelMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000003C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeChannelMaskWithCompletionHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ChannelMask response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ChannelMask read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsChannelMask : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsChannelMask()
        : SubscribeAttribute("channel-mask")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsChannelMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000003C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeChannelMaskWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ChannelMask response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OperationalDatasetComponents
 */
class ReadThreadNetworkDiagnosticsOperationalDatasetComponents : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsOperationalDatasetComponents()
        : ReadAttribute("operational-dataset-components")
    {
    }

    ~ReadThreadNetworkDiagnosticsOperationalDatasetComponents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000003D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeOperationalDatasetComponentsWithCompletionHandler:^(
            MTRThreadNetworkDiagnosticsClusterOperationalDatasetComponents * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.OperationalDatasetComponents response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics OperationalDatasetComponents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsOperationalDatasetComponents : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsOperationalDatasetComponents()
        : SubscribeAttribute("operational-dataset-components")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsOperationalDatasetComponents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000003D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOperationalDatasetComponentsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(
                MTRThreadNetworkDiagnosticsClusterOperationalDatasetComponents * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.OperationalDatasetComponents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveNetworkFaultsList
 */
class ReadThreadNetworkDiagnosticsActiveNetworkFaultsList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsActiveNetworkFaultsList()
        : ReadAttribute("active-network-faults-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsActiveNetworkFaultsList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000003E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeActiveNetworkFaultsListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ActiveNetworkFaultsList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ActiveNetworkFaultsList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsActiveNetworkFaultsList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsActiveNetworkFaultsList()
        : SubscribeAttribute("active-network-faults-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsActiveNetworkFaultsList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000003E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveNetworkFaultsListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ActiveNetworkFaultsList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadThreadNetworkDiagnosticsGeneratedCommandList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadThreadNetworkDiagnosticsAcceptedCommandList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadThreadNetworkDiagnosticsAttributeList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadThreadNetworkDiagnosticsFeatureMap : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadThreadNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadThreadNetworkDiagnosticsClusterRevision : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadThreadNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster WiFiNetworkDiagnostics                                      | 0x0036 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCounts                                                       |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Bssid                                                             | 0x0000 |
| * SecurityType                                                      | 0x0001 |
| * WiFiVersion                                                       | 0x0002 |
| * ChannelNumber                                                     | 0x0003 |
| * Rssi                                                              | 0x0004 |
| * BeaconLostCount                                                   | 0x0005 |
| * BeaconRxCount                                                     | 0x0006 |
| * PacketMulticastRxCount                                            | 0x0007 |
| * PacketMulticastTxCount                                            | 0x0008 |
| * PacketUnicastRxCount                                              | 0x0009 |
| * PacketUnicastTxCount                                              | 0x000A |
| * CurrentMaxRate                                                    | 0x000B |
| * OverrunCount                                                      | 0x000C |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * Disconnection                                                     | 0x0000 |
| * AssociationFailure                                                | 0x0001 |
| * ConnectionStatus                                                  | 0x0002 |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCounts
 */
class WiFiNetworkDiagnosticsResetCounts : public ClusterCommand {
public:
    WiFiNetworkDiagnosticsResetCounts()
        : ClusterCommand("reset-counts")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint: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
                         completionHandler:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute Bssid
 */
class ReadWiFiNetworkDiagnosticsBssid : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsBssid()
        : ReadAttribute("bssid")
    {
    }

    ~ReadWiFiNetworkDiagnosticsBssid() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeBssidWithCompletionHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.Bssid response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics Bssid read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsBssid : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsBssid()
        : SubscribeAttribute("bssid")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsBssid() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBssidWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.Bssid response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SecurityType
 */
class ReadWiFiNetworkDiagnosticsSecurityType : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsSecurityType()
        : ReadAttribute("security-type")
    {
    }

    ~ReadWiFiNetworkDiagnosticsSecurityType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeSecurityTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.SecurityType response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics SecurityType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsSecurityType : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsSecurityType()
        : SubscribeAttribute("security-type")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsSecurityType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSecurityTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.SecurityType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiFiVersion
 */
class ReadWiFiNetworkDiagnosticsWiFiVersion : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsWiFiVersion()
        : ReadAttribute("wi-fi-version")
    {
    }

    ~ReadWiFiNetworkDiagnosticsWiFiVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeWiFiVersionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.WiFiVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics WiFiVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsWiFiVersion : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsWiFiVersion()
        : SubscribeAttribute("wi-fi-version")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsWiFiVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWiFiVersionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.WiFiVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChannelNumber
 */
class ReadWiFiNetworkDiagnosticsChannelNumber : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsChannelNumber()
        : ReadAttribute("channel-number")
    {
    }

    ~ReadWiFiNetworkDiagnosticsChannelNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeChannelNumberWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.ChannelNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics ChannelNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsChannelNumber : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsChannelNumber()
        : SubscribeAttribute("channel-number")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsChannelNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeChannelNumberWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.ChannelNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Rssi
 */
class ReadWiFiNetworkDiagnosticsRssi : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsRssi()
        : ReadAttribute("rssi")
    {
    }

    ~ReadWiFiNetworkDiagnosticsRssi() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeRssiWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.Rssi response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics Rssi read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsRssi : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsRssi()
        : SubscribeAttribute("rssi")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsRssi() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRssiWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.Rssi response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BeaconLostCount
 */
class ReadWiFiNetworkDiagnosticsBeaconLostCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsBeaconLostCount()
        : ReadAttribute("beacon-lost-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsBeaconLostCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeBeaconLostCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.BeaconLostCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics BeaconLostCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsBeaconLostCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsBeaconLostCount()
        : SubscribeAttribute("beacon-lost-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsBeaconLostCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBeaconLostCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.BeaconLostCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BeaconRxCount
 */
class ReadWiFiNetworkDiagnosticsBeaconRxCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsBeaconRxCount()
        : ReadAttribute("beacon-rx-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsBeaconRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeBeaconRxCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.BeaconRxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics BeaconRxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsBeaconRxCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsBeaconRxCount()
        : SubscribeAttribute("beacon-rx-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsBeaconRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBeaconRxCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.BeaconRxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketMulticastRxCount
 */
class ReadWiFiNetworkDiagnosticsPacketMulticastRxCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsPacketMulticastRxCount()
        : ReadAttribute("packet-multicast-rx-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsPacketMulticastRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePacketMulticastRxCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.PacketMulticastRxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics PacketMulticastRxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastRxCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastRxCount()
        : SubscribeAttribute("packet-multicast-rx-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePacketMulticastRxCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.PacketMulticastRxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketMulticastTxCount
 */
class ReadWiFiNetworkDiagnosticsPacketMulticastTxCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsPacketMulticastTxCount()
        : ReadAttribute("packet-multicast-tx-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsPacketMulticastTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePacketMulticastTxCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.PacketMulticastTxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics PacketMulticastTxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastTxCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastTxCount()
        : SubscribeAttribute("packet-multicast-tx-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePacketMulticastTxCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.PacketMulticastTxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketUnicastRxCount
 */
class ReadWiFiNetworkDiagnosticsPacketUnicastRxCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsPacketUnicastRxCount()
        : ReadAttribute("packet-unicast-rx-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsPacketUnicastRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePacketUnicastRxCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.PacketUnicastRxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics PacketUnicastRxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastRxCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastRxCount()
        : SubscribeAttribute("packet-unicast-rx-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePacketUnicastRxCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.PacketUnicastRxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketUnicastTxCount
 */
class ReadWiFiNetworkDiagnosticsPacketUnicastTxCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsPacketUnicastTxCount()
        : ReadAttribute("packet-unicast-tx-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsPacketUnicastTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePacketUnicastTxCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.PacketUnicastTxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics PacketUnicastTxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastTxCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastTxCount()
        : SubscribeAttribute("packet-unicast-tx-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePacketUnicastTxCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.PacketUnicastTxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentMaxRate
 */
class ReadWiFiNetworkDiagnosticsCurrentMaxRate : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsCurrentMaxRate()
        : ReadAttribute("current-max-rate")
    {
    }

    ~ReadWiFiNetworkDiagnosticsCurrentMaxRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeCurrentMaxRateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.CurrentMaxRate response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics CurrentMaxRate read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsCurrentMaxRate : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsCurrentMaxRate()
        : SubscribeAttribute("current-max-rate")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsCurrentMaxRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentMaxRateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.CurrentMaxRate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OverrunCount
 */
class ReadWiFiNetworkDiagnosticsOverrunCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsOverrunCount()
        : ReadAttribute("overrun-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeOverrunCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.OverrunCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics OverrunCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsOverrunCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsOverrunCount()
        : SubscribeAttribute("overrun-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOverrunCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.OverrunCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadWiFiNetworkDiagnosticsGeneratedCommandList : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadWiFiNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadWiFiNetworkDiagnosticsAcceptedCommandList : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadWiFiNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadWiFiNetworkDiagnosticsAttributeList : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadWiFiNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadWiFiNetworkDiagnosticsFeatureMap : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadWiFiNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadWiFiNetworkDiagnosticsClusterRevision : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadWiFiNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster EthernetNetworkDiagnostics                                  | 0x0037 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCounts                                                       |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * PHYRate                                                           | 0x0000 |
| * FullDuplex                                                        | 0x0001 |
| * PacketRxCount                                                     | 0x0002 |
| * PacketTxCount                                                     | 0x0003 |
| * TxErrCount                                                        | 0x0004 |
| * CollisionCount                                                    | 0x0005 |
| * OverrunCount                                                      | 0x0006 |
| * CarrierDetect                                                     | 0x0007 |
| * TimeSinceReset                                                    | 0x0008 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCounts
 */
class EthernetNetworkDiagnosticsResetCounts : public ClusterCommand {
public:
    EthernetNetworkDiagnosticsResetCounts()
        : ClusterCommand("reset-counts")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint: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
                         completionHandler:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute PHYRate
 */
class ReadEthernetNetworkDiagnosticsPHYRate : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsPHYRate()
        : ReadAttribute("phyrate")
    {
    }

    ~ReadEthernetNetworkDiagnosticsPHYRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePHYRateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.PHYRate response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics PHYRate read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsPHYRate : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsPHYRate()
        : SubscribeAttribute("phyrate")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsPHYRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePHYRateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.PHYRate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FullDuplex
 */
class ReadEthernetNetworkDiagnosticsFullDuplex : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsFullDuplex()
        : ReadAttribute("full-duplex")
    {
    }

    ~ReadEthernetNetworkDiagnosticsFullDuplex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFullDuplexWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.FullDuplex response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics FullDuplex read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsFullDuplex : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsFullDuplex()
        : SubscribeAttribute("full-duplex")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsFullDuplex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFullDuplexWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.FullDuplex response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketRxCount
 */
class ReadEthernetNetworkDiagnosticsPacketRxCount : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsPacketRxCount()
        : ReadAttribute("packet-rx-count")
    {
    }

    ~ReadEthernetNetworkDiagnosticsPacketRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePacketRxCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.PacketRxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics PacketRxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsPacketRxCount : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsPacketRxCount()
        : SubscribeAttribute("packet-rx-count")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsPacketRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePacketRxCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.PacketRxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketTxCount
 */
class ReadEthernetNetworkDiagnosticsPacketTxCount : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsPacketTxCount()
        : ReadAttribute("packet-tx-count")
    {
    }

    ~ReadEthernetNetworkDiagnosticsPacketTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePacketTxCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.PacketTxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics PacketTxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsPacketTxCount : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsPacketTxCount()
        : SubscribeAttribute("packet-tx-count")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsPacketTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePacketTxCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.PacketTxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxErrCount
 */
class ReadEthernetNetworkDiagnosticsTxErrCount : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsTxErrCount()
        : ReadAttribute("tx-err-count")
    {
    }

    ~ReadEthernetNetworkDiagnosticsTxErrCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTxErrCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.TxErrCount response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics TxErrCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsTxErrCount : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsTxErrCount()
        : SubscribeAttribute("tx-err-count")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsTxErrCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTxErrCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.TxErrCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CollisionCount
 */
class ReadEthernetNetworkDiagnosticsCollisionCount : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsCollisionCount()
        : ReadAttribute("collision-count")
    {
    }

    ~ReadEthernetNetworkDiagnosticsCollisionCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeCollisionCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.CollisionCount response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics CollisionCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsCollisionCount : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsCollisionCount()
        : SubscribeAttribute("collision-count")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsCollisionCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCollisionCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.CollisionCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OverrunCount
 */
class ReadEthernetNetworkDiagnosticsOverrunCount : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsOverrunCount()
        : ReadAttribute("overrun-count")
    {
    }

    ~ReadEthernetNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeOverrunCountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.OverrunCount response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics OverrunCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsOverrunCount : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsOverrunCount()
        : SubscribeAttribute("overrun-count")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOverrunCountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.OverrunCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CarrierDetect
 */
class ReadEthernetNetworkDiagnosticsCarrierDetect : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsCarrierDetect()
        : ReadAttribute("carrier-detect")
    {
    }

    ~ReadEthernetNetworkDiagnosticsCarrierDetect() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeCarrierDetectWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.CarrierDetect response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics CarrierDetect read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsCarrierDetect : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsCarrierDetect()
        : SubscribeAttribute("carrier-detect")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsCarrierDetect() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCarrierDetectWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.CarrierDetect response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TimeSinceReset
 */
class ReadEthernetNetworkDiagnosticsTimeSinceReset : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsTimeSinceReset()
        : ReadAttribute("time-since-reset")
    {
    }

    ~ReadEthernetNetworkDiagnosticsTimeSinceReset() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTimeSinceResetWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.TimeSinceReset response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics TimeSinceReset read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsTimeSinceReset : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsTimeSinceReset()
        : SubscribeAttribute("time-since-reset")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsTimeSinceReset() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTimeSinceResetWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.TimeSinceReset response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadEthernetNetworkDiagnosticsGeneratedCommandList : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadEthernetNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadEthernetNetworkDiagnosticsAcceptedCommandList : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadEthernetNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadEthernetNetworkDiagnosticsAttributeList : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadEthernetNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadEthernetNetworkDiagnosticsFeatureMap : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadEthernetNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadEthernetNetworkDiagnosticsClusterRevision : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadEthernetNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster BridgedDeviceBasic                                          | 0x0039 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * VendorName                                                        | 0x0001 |
| * VendorID                                                          | 0x0002 |
| * ProductName                                                       | 0x0003 |
| * NodeLabel                                                         | 0x0005 |
| * HardwareVersion                                                   | 0x0007 |
| * HardwareVersionString                                             | 0x0008 |
| * SoftwareVersion                                                   | 0x0009 |
| * SoftwareVersionString                                             | 0x000A |
| * ManufacturingDate                                                 | 0x000B |
| * PartNumber                                                        | 0x000C |
| * ProductURL                                                        | 0x000D |
| * ProductLabel                                                      | 0x000E |
| * SerialNumber                                                      | 0x000F |
| * Reachable                                                         | 0x0011 |
| * UniqueID                                                          | 0x0012 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StartUp                                                           | 0x0000 |
| * ShutDown                                                          | 0x0001 |
| * Leave                                                             | 0x0002 |
| * ReachableChanged                                                  | 0x0003 |
\*----------------------------------------------------------------------------*/

/*
 * Attribute VendorName
 */
class ReadBridgedDeviceBasicVendorName : public ReadAttribute {
public:
    ReadBridgedDeviceBasicVendorName()
        : ReadAttribute("vendor-name")
    {
    }

    ~ReadBridgedDeviceBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeVendorNameWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.VendorName response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic VendorName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicVendorName : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicVendorName()
        : SubscribeAttribute("vendor-name")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeVendorNameWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.VendorName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorID
 */
class ReadBridgedDeviceBasicVendorID : public ReadAttribute {
public:
    ReadBridgedDeviceBasicVendorID()
        : ReadAttribute("vendor-id")
    {
    }

    ~ReadBridgedDeviceBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeVendorIDWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.VendorID response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic VendorID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicVendorID : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicVendorID()
        : SubscribeAttribute("vendor-id")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeVendorIDWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.VendorID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductName
 */
class ReadBridgedDeviceBasicProductName : public ReadAttribute {
public:
    ReadBridgedDeviceBasicProductName()
        : ReadAttribute("product-name")
    {
    }

    ~ReadBridgedDeviceBasicProductName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeProductNameWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.ProductName response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic ProductName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicProductName : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicProductName()
        : SubscribeAttribute("product-name")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicProductName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeProductNameWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.ProductName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NodeLabel
 */
class ReadBridgedDeviceBasicNodeLabel : public ReadAttribute {
public:
    ReadBridgedDeviceBasicNodeLabel()
        : ReadAttribute("node-label")
    {
    }

    ~ReadBridgedDeviceBasicNodeLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeNodeLabelWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.NodeLabel response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic NodeLabel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBridgedDeviceBasicNodeLabel : public WriteAttribute {
public:
    WriteBridgedDeviceBasicNodeLabel()
        : WriteAttribute("node-label")
    {
        AddArgument("attr-name", "node-label");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBridgedDeviceBasicNodeLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeNodeLabelWithValue:value
                                           params:params
                                completionHandler:^(NSError * _Nullable error) {
                                    if (error != nil) {
                                        LogNSError("BridgedDeviceBasic NodeLabel write Error", error);
                                    }
                                    SetCommandExitStatus(error);
                                }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBridgedDeviceBasicNodeLabel : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicNodeLabel()
        : SubscribeAttribute("node-label")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicNodeLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNodeLabelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.NodeLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareVersion
 */
class ReadBridgedDeviceBasicHardwareVersion : public ReadAttribute {
public:
    ReadBridgedDeviceBasicHardwareVersion()
        : ReadAttribute("hardware-version")
    {
    }

    ~ReadBridgedDeviceBasicHardwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeHardwareVersionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.HardwareVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic HardwareVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicHardwareVersion : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicHardwareVersion()
        : SubscribeAttribute("hardware-version")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicHardwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeHardwareVersionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.HardwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareVersionString
 */
class ReadBridgedDeviceBasicHardwareVersionString : public ReadAttribute {
public:
    ReadBridgedDeviceBasicHardwareVersionString()
        : ReadAttribute("hardware-version-string")
    {
    }

    ~ReadBridgedDeviceBasicHardwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeHardwareVersionStringWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.HardwareVersionString response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic HardwareVersionString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicHardwareVersionString : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicHardwareVersionString()
        : SubscribeAttribute("hardware-version-string")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicHardwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeHardwareVersionStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.HardwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoftwareVersion
 */
class ReadBridgedDeviceBasicSoftwareVersion : public ReadAttribute {
public:
    ReadBridgedDeviceBasicSoftwareVersion()
        : ReadAttribute("software-version")
    {
    }

    ~ReadBridgedDeviceBasicSoftwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeSoftwareVersionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.SoftwareVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic SoftwareVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicSoftwareVersion : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicSoftwareVersion()
        : SubscribeAttribute("software-version")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicSoftwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSoftwareVersionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.SoftwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoftwareVersionString
 */
class ReadBridgedDeviceBasicSoftwareVersionString : public ReadAttribute {
public:
    ReadBridgedDeviceBasicSoftwareVersionString()
        : ReadAttribute("software-version-string")
    {
    }

    ~ReadBridgedDeviceBasicSoftwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeSoftwareVersionStringWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.SoftwareVersionString response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic SoftwareVersionString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicSoftwareVersionString : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicSoftwareVersionString()
        : SubscribeAttribute("software-version-string")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicSoftwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSoftwareVersionStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.SoftwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ManufacturingDate
 */
class ReadBridgedDeviceBasicManufacturingDate : public ReadAttribute {
public:
    ReadBridgedDeviceBasicManufacturingDate()
        : ReadAttribute("manufacturing-date")
    {
    }

    ~ReadBridgedDeviceBasicManufacturingDate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeManufacturingDateWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.ManufacturingDate response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic ManufacturingDate read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicManufacturingDate : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicManufacturingDate()
        : SubscribeAttribute("manufacturing-date")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicManufacturingDate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeManufacturingDateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.ManufacturingDate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PartNumber
 */
class ReadBridgedDeviceBasicPartNumber : public ReadAttribute {
public:
    ReadBridgedDeviceBasicPartNumber()
        : ReadAttribute("part-number")
    {
    }

    ~ReadBridgedDeviceBasicPartNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributePartNumberWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.PartNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic PartNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicPartNumber : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicPartNumber()
        : SubscribeAttribute("part-number")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicPartNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePartNumberWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.PartNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductURL
 */
class ReadBridgedDeviceBasicProductURL : public ReadAttribute {
public:
    ReadBridgedDeviceBasicProductURL()
        : ReadAttribute("product-url")
    {
    }

    ~ReadBridgedDeviceBasicProductURL() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeProductURLWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.ProductURL response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic ProductURL read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicProductURL : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicProductURL()
        : SubscribeAttribute("product-url")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicProductURL() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeProductURLWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.ProductURL response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductLabel
 */
class ReadBridgedDeviceBasicProductLabel : public ReadAttribute {
public:
    ReadBridgedDeviceBasicProductLabel()
        : ReadAttribute("product-label")
    {
    }

    ~ReadBridgedDeviceBasicProductLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeProductLabelWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.ProductLabel response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic ProductLabel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicProductLabel : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicProductLabel()
        : SubscribeAttribute("product-label")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicProductLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeProductLabelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.ProductLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SerialNumber
 */
class ReadBridgedDeviceBasicSerialNumber : public ReadAttribute {
public:
    ReadBridgedDeviceBasicSerialNumber()
        : ReadAttribute("serial-number")
    {
    }

    ~ReadBridgedDeviceBasicSerialNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeSerialNumberWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.SerialNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic SerialNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicSerialNumber : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicSerialNumber()
        : SubscribeAttribute("serial-number")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicSerialNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSerialNumberWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.SerialNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Reachable
 */
class ReadBridgedDeviceBasicReachable : public ReadAttribute {
public:
    ReadBridgedDeviceBasicReachable()
        : ReadAttribute("reachable")
    {
    }

    ~ReadBridgedDeviceBasicReachable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeReachableWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.Reachable response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic Reachable read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicReachable : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicReachable()
        : SubscribeAttribute("reachable")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicReachable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeReachableWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.Reachable response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UniqueID
 */
class ReadBridgedDeviceBasicUniqueID : public ReadAttribute {
public:
    ReadBridgedDeviceBasicUniqueID()
        : ReadAttribute("unique-id")
    {
    }

    ~ReadBridgedDeviceBasicUniqueID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeUniqueIDWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.UniqueID response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic UniqueID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicUniqueID : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicUniqueID()
        : SubscribeAttribute("unique-id")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicUniqueID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUniqueIDWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.UniqueID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBridgedDeviceBasicGeneratedCommandList : public ReadAttribute {
public:
    ReadBridgedDeviceBasicGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBridgedDeviceBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBridgedDeviceBasicAcceptedCommandList : public ReadAttribute {
public:
    ReadBridgedDeviceBasicAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBridgedDeviceBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBridgedDeviceBasicAttributeList : public ReadAttribute {
public:
    ReadBridgedDeviceBasicAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBridgedDeviceBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBridgedDeviceBasicFeatureMap : public ReadAttribute {
public:
    ReadBridgedDeviceBasicFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBridgedDeviceBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBridgedDeviceBasicClusterRevision : public ReadAttribute {
public:
    ReadBridgedDeviceBasicClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBridgedDeviceBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Switch                                                      | 0x003B |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * NumberOfPositions                                                 | 0x0000 |
| * CurrentPosition                                                   | 0x0001 |
| * MultiPressMax                                                     | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * SwitchLatched                                                     | 0x0000 |
| * InitialPress                                                      | 0x0001 |
| * LongPress                                                         | 0x0002 |
| * ShortRelease                                                      | 0x0003 |
| * LongRelease                                                       | 0x0004 |
| * MultiPressOngoing                                                 | 0x0005 |
| * MultiPressComplete                                                | 0x0006 |
\*----------------------------------------------------------------------------*/

/*
 * Attribute NumberOfPositions
 */
class ReadSwitchNumberOfPositions : public ReadAttribute {
public:
    ReadSwitchNumberOfPositions()
        : ReadAttribute("number-of-positions")
    {
    }

    ~ReadSwitchNumberOfPositions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        [cluster readAttributeNumberOfPositionsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.NumberOfPositions response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch NumberOfPositions read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchNumberOfPositions : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchNumberOfPositions()
        : SubscribeAttribute("number-of-positions")
    {
    }

    ~SubscribeAttributeSwitchNumberOfPositions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfPositionsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.NumberOfPositions response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPosition
 */
class ReadSwitchCurrentPosition : public ReadAttribute {
public:
    ReadSwitchCurrentPosition()
        : ReadAttribute("current-position")
    {
    }

    ~ReadSwitchCurrentPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.CurrentPosition response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch CurrentPosition read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchCurrentPosition : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchCurrentPosition()
        : SubscribeAttribute("current-position")
    {
    }

    ~SubscribeAttributeSwitchCurrentPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentPositionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.CurrentPosition response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MultiPressMax
 */
class ReadSwitchMultiPressMax : public ReadAttribute {
public:
    ReadSwitchMultiPressMax()
        : ReadAttribute("multi-press-max")
    {
    }

    ~ReadSwitchMultiPressMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        [cluster readAttributeMultiPressMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.MultiPressMax response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch MultiPressMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchMultiPressMax : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchMultiPressMax()
        : SubscribeAttribute("multi-press-max")
    {
    }

    ~SubscribeAttributeSwitchMultiPressMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMultiPressMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.MultiPressMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadSwitchGeneratedCommandList : public ReadAttribute {
public:
    ReadSwitchGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadSwitchGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeSwitchGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadSwitchAcceptedCommandList : public ReadAttribute {
public:
    ReadSwitchAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadSwitchAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeSwitchAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadSwitchAttributeList : public ReadAttribute {
public:
    ReadSwitchAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadSwitchAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeSwitchAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadSwitchFeatureMap : public ReadAttribute {
public:
    ReadSwitchFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadSwitchFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeSwitchFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadSwitchClusterRevision : public ReadAttribute {
public:
    ReadSwitchClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadSwitchClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeSwitchClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                             endpoint:endpointId
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster AdministratorCommissioning                                  | 0x003C |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * OpenCommissioningWindow                                           |   0x00 |
| * OpenBasicCommissioningWindow                                      |   0x01 |
| * RevokeCommissioning                                               |   0x02 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * WindowStatus                                                      | 0x0000 |
| * AdminFabricIndex                                                  | 0x0001 |
| * AdminVendorId                                                     | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command OpenCommissioningWindow
 */
class AdministratorCommissioningOpenCommissioningWindow : public ClusterCommand {
public:
    AdministratorCommissioningOpenCommissioningWindow()
        : ClusterCommand("open-commissioning-window")
    {
        AddArgument("CommissioningTimeout", 0, UINT16_MAX, &mRequest.commissioningTimeout);
        AddArgument("PAKEVerifier", &mRequest.PAKEVerifier);
        AddArgument("Discriminator", 0, UINT16_MAX, &mRequest.discriminator);
        AddArgument("Iterations", 0, UINT32_MAX, &mRequest.iterations);
        AddArgument("Salt", &mRequest.salt);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        __auto_type * params = [[MTRAdministratorCommissioningClusterOpenCommissioningWindowParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.commissioningTimeout = [NSNumber numberWithUnsignedShort:mRequest.commissioningTimeout];
        params.pakeVerifier = [NSData dataWithBytes:mRequest.PAKEVerifier.data() length:mRequest.PAKEVerifier.size()];
        params.discriminator = [NSNumber numberWithUnsignedShort:mRequest.discriminator];
        params.iterations = [NSNumber numberWithUnsignedInt:mRequest.iterations];
        params.salt = [NSData dataWithBytes:mRequest.salt.data() length:mRequest.salt.size()];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster openCommissioningWindowWithParams:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         responsesNeeded--;
                                         if (error != nil) {
                                             mError = error;
                                             LogNSError("Error", error);
                                         }
                                         if (responsesNeeded == 0) {
                                             SetCommandExitStatus(mError);
                                         }
                                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AdministratorCommissioning::Commands::OpenCommissioningWindow::Type mRequest;
};

/*
 * Command OpenBasicCommissioningWindow
 */
class AdministratorCommissioningOpenBasicCommissioningWindow : public ClusterCommand {
public:
    AdministratorCommissioningOpenBasicCommissioningWindow()
        : ClusterCommand("open-basic-commissioning-window")
    {
        AddArgument("CommissioningTimeout", 0, UINT16_MAX, &mRequest.commissioningTimeout);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint: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
                                          completionHandler:^(NSError * _Nullable error) {
                                              responsesNeeded--;
                                              if (error != nil) {
                                                  mError = error;
                                                  LogNSError("Error", error);
                                              }
                                              if (responsesNeeded == 0) {
                                                  SetCommandExitStatus(mError);
                                              }
                                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Type mRequest;
};

/*
 * Command RevokeCommissioning
 */
class AdministratorCommissioningRevokeCommissioning : public ClusterCommand {
public:
    AdministratorCommissioningRevokeCommissioning()
        : ClusterCommand("revoke-commissioning")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint: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
                                 completionHandler:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute WindowStatus
 */
class ReadAdministratorCommissioningWindowStatus : public ReadAttribute {
public:
    ReadAdministratorCommissioningWindowStatus()
        : ReadAttribute("window-status")
    {
    }

    ~ReadAdministratorCommissioningWindowStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeWindowStatusWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.WindowStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning WindowStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningWindowStatus : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningWindowStatus()
        : SubscribeAttribute("window-status")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningWindowStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWindowStatusWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.WindowStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AdminFabricIndex
 */
class ReadAdministratorCommissioningAdminFabricIndex : public ReadAttribute {
public:
    ReadAdministratorCommissioningAdminFabricIndex()
        : ReadAttribute("admin-fabric-index")
    {
    }

    ~ReadAdministratorCommissioningAdminFabricIndex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAdminFabricIndexWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.AdminFabricIndex response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning AdminFabricIndex read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningAdminFabricIndex : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningAdminFabricIndex()
        : SubscribeAttribute("admin-fabric-index")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningAdminFabricIndex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAdminFabricIndexWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.AdminFabricIndex response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AdminVendorId
 */
class ReadAdministratorCommissioningAdminVendorId : public ReadAttribute {
public:
    ReadAdministratorCommissioningAdminVendorId()
        : ReadAttribute("admin-vendor-id")
    {
    }

    ~ReadAdministratorCommissioningAdminVendorId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAdminVendorIdWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.AdminVendorId response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning AdminVendorId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningAdminVendorId : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningAdminVendorId()
        : SubscribeAttribute("admin-vendor-id")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningAdminVendorId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAdminVendorIdWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.AdminVendorId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadAdministratorCommissioningGeneratedCommandList : public ReadAttribute {
public:
    ReadAdministratorCommissioningGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadAdministratorCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadAdministratorCommissioningAcceptedCommandList : public ReadAttribute {
public:
    ReadAdministratorCommissioningAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadAdministratorCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadAdministratorCommissioningAttributeList : public ReadAttribute {
public:
    ReadAdministratorCommissioningAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadAdministratorCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadAdministratorCommissioningFeatureMap : public ReadAttribute {
public:
    ReadAdministratorCommissioningFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadAdministratorCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadAdministratorCommissioningClusterRevision : public ReadAttribute {
public:
    ReadAdministratorCommissioningClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadAdministratorCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OperationalCredentials                                      | 0x003E |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * AttestationRequest                                                |   0x00 |
| * CertificateChainRequest                                           |   0x02 |
| * CSRRequest                                                        |   0x04 |
| * AddNOC                                                            |   0x06 |
| * UpdateNOC                                                         |   0x07 |
| * UpdateFabricLabel                                                 |   0x09 |
| * RemoveFabric                                                      |   0x0A |
| * AddTrustedRootCertificate                                         |   0x0B |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * NOCs                                                              | 0x0000 |
| * Fabrics                                                           | 0x0001 |
| * SupportedFabrics                                                  | 0x0002 |
| * CommissionedFabrics                                               | 0x0003 |
| * TrustedRootCertificates                                           | 0x0004 |
| * CurrentFabricIndex                                                | 0x0005 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command AttestationRequest
 */
class OperationalCredentialsAttestationRequest : public ClusterCommand {
public:
    OperationalCredentialsAttestationRequest()
        : ClusterCommand("attestation-request")
    {
        AddArgument("AttestationNonce", &mRequest.attestationNonce);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint: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
                                completionHandler:^(MTROperationalCredentialsClusterAttestationResponseParams * _Nullable values,
                                    NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::AttestationRequest::Type mRequest;
};

/*
 * Command CertificateChainRequest
 */
class OperationalCredentialsCertificateChainRequest : public ClusterCommand {
public:
    OperationalCredentialsCertificateChainRequest()
        : ClusterCommand("certificate-chain-request")
    {
        AddArgument("CertificateType", 0, UINT8_MAX, &mRequest.certificateType);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        __auto_type * params = [[MTROperationalCredentialsClusterCertificateChainRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.certificateType = [NSNumber numberWithUnsignedChar:mRequest.certificateType];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster certificateChainRequestWithParams:params
                                     completionHandler:^(
                                         MTROperationalCredentialsClusterCertificateChainResponseParams * _Nullable values,
                                         NSError * _Nullable error) {
                                         NSLog(@"Values: %@", values);
                                         responsesNeeded--;
                                         if (error != nil) {
                                             mError = error;
                                             LogNSError("Error", error);
                                         }
                                         if (responsesNeeded == 0) {
                                             SetCommandExitStatus(mError);
                                         }
                                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::CertificateChainRequest::Type mRequest;
};

/*
 * Command CSRRequest
 */
class OperationalCredentialsCSRRequest : public ClusterCommand {
public:
    OperationalCredentialsCSRRequest()
        : ClusterCommand("csrrequest")
    {
        AddArgument("CSRNonce", &mRequest.CSRNonce);
        AddArgument("IsForUpdateNOC", 0, 1, &mRequest.isForUpdateNOC);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint: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
                        completionHandler:^(
                            MTROperationalCredentialsClusterCSRResponseParams * _Nullable values, NSError * _Nullable error) {
                            NSLog(@"Values: %@", values);
                            responsesNeeded--;
                            if (error != nil) {
                                mError = error;
                                LogNSError("Error", error);
                            }
                            if (responsesNeeded == 0) {
                                SetCommandExitStatus(mError);
                            }
                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::CSRRequest::Type mRequest;
};

/*
 * Command AddNOC
 */
class OperationalCredentialsAddNOC : public ClusterCommand {
public:
    OperationalCredentialsAddNOC()
        : ClusterCommand("add-noc")
    {
        AddArgument("NOCValue", &mRequest.NOCValue);
        AddArgument("ICACValue", &mRequest.ICACValue);
        AddArgument("IPKValue", &mRequest.IPKValue);
        AddArgument("CaseAdminSubject", 0, UINT64_MAX, &mRequest.caseAdminSubject);
        AddArgument("AdminVendorId", 0, UINT16_MAX, &mRequest.adminVendorId);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint: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
                    completionHandler:^(
                        MTROperationalCredentialsClusterNOCResponseParams * _Nullable values, NSError * _Nullable error) {
                        NSLog(@"Values: %@", values);
                        responsesNeeded--;
                        if (error != nil) {
                            mError = error;
                            LogNSError("Error", error);
                        }
                        if (responsesNeeded == 0) {
                            SetCommandExitStatus(mError);
                        }
                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::AddNOC::Type mRequest;
};

/*
 * Command UpdateNOC
 */
class OperationalCredentialsUpdateNOC : public ClusterCommand {
public:
    OperationalCredentialsUpdateNOC()
        : ClusterCommand("update-noc")
    {
        AddArgument("NOCValue", &mRequest.NOCValue);
        AddArgument("ICACValue", &mRequest.ICACValue);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint: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
                       completionHandler:^(
                           MTROperationalCredentialsClusterNOCResponseParams * _Nullable values, NSError * _Nullable error) {
                           NSLog(@"Values: %@", values);
                           responsesNeeded--;
                           if (error != nil) {
                               mError = error;
                               LogNSError("Error", error);
                           }
                           if (responsesNeeded == 0) {
                               SetCommandExitStatus(mError);
                           }
                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::UpdateNOC::Type mRequest;
};

/*
 * Command UpdateFabricLabel
 */
class OperationalCredentialsUpdateFabricLabel : public ClusterCommand {
public:
    OperationalCredentialsUpdateFabricLabel()
        : ClusterCommand("update-fabric-label")
    {
        AddArgument("Label", &mRequest.label);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint: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
                               completionHandler:^(MTROperationalCredentialsClusterNOCResponseParams * _Nullable values,
                                   NSError * _Nullable error) {
                                   NSLog(@"Values: %@", values);
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::UpdateFabricLabel::Type mRequest;
};

/*
 * Command RemoveFabric
 */
class OperationalCredentialsRemoveFabric : public ClusterCommand {
public:
    OperationalCredentialsRemoveFabric()
        : ClusterCommand("remove-fabric")
    {
        AddArgument("FabricIndex", 0, UINT8_MAX, &mRequest.fabricIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint: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
                          completionHandler:^(
                              MTROperationalCredentialsClusterNOCResponseParams * _Nullable values, NSError * _Nullable error) {
                              NSLog(@"Values: %@", values);
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::RemoveFabric::Type mRequest;
};

/*
 * Command AddTrustedRootCertificate
 */
class OperationalCredentialsAddTrustedRootCertificate : public ClusterCommand {
public:
    OperationalCredentialsAddTrustedRootCertificate()
        : ClusterCommand("add-trusted-root-certificate")
    {
        AddArgument("RootCertificate", &mRequest.rootCertificate);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        __auto_type * params = [[MTROperationalCredentialsClusterAddTrustedRootCertificateParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.rootCertificate = [NSData dataWithBytes:mRequest.rootCertificate.data() length:mRequest.rootCertificate.size()];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster addTrustedRootCertificateWithParams:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::AddTrustedRootCertificate::Type mRequest;
};

/*
 * Attribute NOCs
 */
class ReadOperationalCredentialsNOCs : public ReadAttribute {
public:
    ReadOperationalCredentialsNOCs()
        : ReadAttribute("nocs")
    {
    }

    ~ReadOperationalCredentialsNOCs() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster readAttributeNOCsWithParams:params
                           completionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                               NSLog(@"OperationalCredentials.NOCs response %@", [value description]);
                               if (error != nil) {
                                   LogNSError("OperationalCredentials NOCs read Error", error);
                               }
                               SetCommandExitStatus(error);
                           }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsNOCs : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsNOCs()
        : SubscribeAttribute("nocs")
    {
    }

    ~SubscribeAttributeOperationalCredentialsNOCs() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNOCsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.NOCs response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Fabrics
 */
class ReadOperationalCredentialsFabrics : public ReadAttribute {
public:
    ReadOperationalCredentialsFabrics()
        : ReadAttribute("fabrics")
    {
    }

    ~ReadOperationalCredentialsFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster readAttributeFabricsWithParams:params
                              completionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                  NSLog(@"OperationalCredentials.Fabrics response %@", [value description]);
                                  if (error != nil) {
                                      LogNSError("OperationalCredentials Fabrics read Error", error);
                                  }
                                  SetCommandExitStatus(error);
                              }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsFabrics : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsFabrics()
        : SubscribeAttribute("fabrics")
    {
    }

    ~SubscribeAttributeOperationalCredentialsFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFabricsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.Fabrics response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedFabrics
 */
class ReadOperationalCredentialsSupportedFabrics : public ReadAttribute {
public:
    ReadOperationalCredentialsSupportedFabrics()
        : ReadAttribute("supported-fabrics")
    {
    }

    ~ReadOperationalCredentialsSupportedFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeSupportedFabricsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.SupportedFabrics response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials SupportedFabrics read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsSupportedFabrics : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsSupportedFabrics()
        : SubscribeAttribute("supported-fabrics")
    {
    }

    ~SubscribeAttributeOperationalCredentialsSupportedFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSupportedFabricsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.SupportedFabrics response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CommissionedFabrics
 */
class ReadOperationalCredentialsCommissionedFabrics : public ReadAttribute {
public:
    ReadOperationalCredentialsCommissionedFabrics()
        : ReadAttribute("commissioned-fabrics")
    {
    }

    ~ReadOperationalCredentialsCommissionedFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeCommissionedFabricsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.CommissionedFabrics response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials CommissionedFabrics read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsCommissionedFabrics : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsCommissionedFabrics()
        : SubscribeAttribute("commissioned-fabrics")
    {
    }

    ~SubscribeAttributeOperationalCredentialsCommissionedFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCommissionedFabricsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.CommissionedFabrics response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TrustedRootCertificates
 */
class ReadOperationalCredentialsTrustedRootCertificates : public ReadAttribute {
public:
    ReadOperationalCredentialsTrustedRootCertificates()
        : ReadAttribute("trusted-root-certificates")
    {
    }

    ~ReadOperationalCredentialsTrustedRootCertificates() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeTrustedRootCertificatesWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.TrustedRootCertificates response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials TrustedRootCertificates read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsTrustedRootCertificates : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsTrustedRootCertificates()
        : SubscribeAttribute("trusted-root-certificates")
    {
    }

    ~SubscribeAttributeOperationalCredentialsTrustedRootCertificates() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTrustedRootCertificatesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.TrustedRootCertificates response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentFabricIndex
 */
class ReadOperationalCredentialsCurrentFabricIndex : public ReadAttribute {
public:
    ReadOperationalCredentialsCurrentFabricIndex()
        : ReadAttribute("current-fabric-index")
    {
    }

    ~ReadOperationalCredentialsCurrentFabricIndex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeCurrentFabricIndexWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.CurrentFabricIndex response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials CurrentFabricIndex read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsCurrentFabricIndex : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsCurrentFabricIndex()
        : SubscribeAttribute("current-fabric-index")
    {
    }

    ~SubscribeAttributeOperationalCredentialsCurrentFabricIndex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentFabricIndexWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.CurrentFabricIndex response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadOperationalCredentialsGeneratedCommandList : public ReadAttribute {
public:
    ReadOperationalCredentialsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadOperationalCredentialsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeOperationalCredentialsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadOperationalCredentialsAcceptedCommandList : public ReadAttribute {
public:
    ReadOperationalCredentialsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadOperationalCredentialsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeOperationalCredentialsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadOperationalCredentialsAttributeList : public ReadAttribute {
public:
    ReadOperationalCredentialsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadOperationalCredentialsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeOperationalCredentialsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadOperationalCredentialsFeatureMap : public ReadAttribute {
public:
    ReadOperationalCredentialsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadOperationalCredentialsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeOperationalCredentialsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadOperationalCredentialsClusterRevision : public ReadAttribute {
public:
    ReadOperationalCredentialsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadOperationalCredentialsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeOperationalCredentialsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster GroupKeyManagement                                          | 0x003F |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * KeySetWrite                                                       |   0x00 |
| * KeySetRead                                                        |   0x01 |
| * KeySetRemove                                                      |   0x03 |
| * KeySetReadAllIndices                                              |   0x04 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GroupKeyMap                                                       | 0x0000 |
| * GroupTable                                                        | 0x0001 |
| * MaxGroupsPerFabric                                                | 0x0002 |
| * MaxGroupKeysPerFabric                                             | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command KeySetWrite
 */
class GroupKeyManagementKeySetWrite : public ClusterCommand {
public:
    GroupKeyManagementKeySetWrite()
        : ClusterCommand("key-set-write")
        , mComplex_GroupKeySet(&mRequest.groupKeySet)
    {
        AddArgument("GroupKeySet", &mComplex_GroupKeySet);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint: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
                         completionHandler:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GroupKeyManagement::Commands::KeySetWrite::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::GroupKeyManagement::Structs::GroupKeySetStruct::Type> mComplex_GroupKeySet;
};

/*
 * Command KeySetRead
 */
class GroupKeyManagementKeySetRead : public ClusterCommand {
public:
    GroupKeyManagementKeySetRead()
        : ClusterCommand("key-set-read")
    {
        AddArgument("GroupKeySetID", 0, UINT16_MAX, &mRequest.groupKeySetID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint: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
                        completionHandler:^(
                            MTRGroupKeyManagementClusterKeySetReadResponseParams * _Nullable values, NSError * _Nullable error) {
                            NSLog(@"Values: %@", values);
                            responsesNeeded--;
                            if (error != nil) {
                                mError = error;
                                LogNSError("Error", error);
                            }
                            if (responsesNeeded == 0) {
                                SetCommandExitStatus(mError);
                            }
                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GroupKeyManagement::Commands::KeySetRead::Type mRequest;
};

/*
 * Command KeySetRemove
 */
class GroupKeyManagementKeySetRemove : public ClusterCommand {
public:
    GroupKeyManagementKeySetRemove()
        : ClusterCommand("key-set-remove")
    {
        AddArgument("GroupKeySetID", 0, UINT16_MAX, &mRequest.groupKeySetID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint: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
                          completionHandler:^(NSError * _Nullable error) {
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GroupKeyManagement::Commands::KeySetRemove::Type mRequest;
};

/*
 * Command KeySetReadAllIndices
 */
class GroupKeyManagementKeySetReadAllIndices : public ClusterCommand {
public:
    GroupKeyManagementKeySetReadAllIndices()
        : ClusterCommand("key-set-read-all-indices")
        , mComplex_GroupKeySetIDs(&mRequest.groupKeySetIDs)
    {
        AddArgument("GroupKeySetIDs", &mComplex_GroupKeySetIDs);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint: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
                             completionHandler:^(MTRGroupKeyManagementClusterKeySetReadAllIndicesResponseParams * _Nullable values,
                                 NSError * _Nullable error) {
                                 NSLog(@"Values: %@", values);
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GroupKeyManagement::Commands::KeySetReadAllIndices::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const uint16_t>> mComplex_GroupKeySetIDs;
};

/*
 * Attribute GroupKeyMap
 */
class ReadGroupKeyManagementGroupKeyMap : public ReadAttribute {
public:
    ReadGroupKeyManagementGroupKeyMap()
        : ReadAttribute("group-key-map")
    {
    }

    ~ReadGroupKeyManagementGroupKeyMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster readAttributeGroupKeyMapWithParams:params
                                  completionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                      NSLog(@"GroupKeyManagement.GroupKeyMap response %@", [value description]);
                                      if (error != nil) {
                                          LogNSError("GroupKeyManagement GroupKeyMap read Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }
};

class WriteGroupKeyManagementGroupKeyMap : public WriteAttribute {
public:
    WriteGroupKeyManagementGroupKeyMap()
        : WriteAttribute("group-key-map")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "group-key-map");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteGroupKeyManagementGroupKeyMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRGroupKeyManagementClusterGroupKeyMapStruct * newElement_0;
                newElement_0 = [MTRGroupKeyManagementClusterGroupKeyMapStruct new];
                newElement_0.groupId = [NSNumber numberWithUnsignedShort:entry_0.groupId];
                newElement_0.groupKeySetID = [NSNumber numberWithUnsignedShort:entry_0.groupKeySetID];
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeGroupKeyMapWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("GroupKeyManagement GroupKeyMap write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::GroupKeyManagement::Structs::GroupKeyMapStruct::Type> mValue;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::GroupKeyManagement::Structs::GroupKeyMapStruct::Type>>
        mComplex;
};

class SubscribeAttributeGroupKeyManagementGroupKeyMap : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementGroupKeyMap()
        : SubscribeAttribute("group-key-map")
    {
    }

    ~SubscribeAttributeGroupKeyManagementGroupKeyMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGroupKeyMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.GroupKeyMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GroupTable
 */
class ReadGroupKeyManagementGroupTable : public ReadAttribute {
public:
    ReadGroupKeyManagementGroupTable()
        : ReadAttribute("group-table")
    {
    }

    ~ReadGroupKeyManagementGroupTable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster readAttributeGroupTableWithParams:params
                                 completionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                     NSLog(@"GroupKeyManagement.GroupTable response %@", [value description]);
                                     if (error != nil) {
                                         LogNSError("GroupKeyManagement GroupTable read Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementGroupTable : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementGroupTable()
        : SubscribeAttribute("group-table")
    {
    }

    ~SubscribeAttributeGroupKeyManagementGroupTable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGroupTableWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.GroupTable response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxGroupsPerFabric
 */
class ReadGroupKeyManagementMaxGroupsPerFabric : public ReadAttribute {
public:
    ReadGroupKeyManagementMaxGroupsPerFabric()
        : ReadAttribute("max-groups-per-fabric")
    {
    }

    ~ReadGroupKeyManagementMaxGroupsPerFabric() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeMaxGroupsPerFabricWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.MaxGroupsPerFabric response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement MaxGroupsPerFabric read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementMaxGroupsPerFabric : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementMaxGroupsPerFabric()
        : SubscribeAttribute("max-groups-per-fabric")
    {
    }

    ~SubscribeAttributeGroupKeyManagementMaxGroupsPerFabric() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxGroupsPerFabricWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.MaxGroupsPerFabric response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxGroupKeysPerFabric
 */
class ReadGroupKeyManagementMaxGroupKeysPerFabric : public ReadAttribute {
public:
    ReadGroupKeyManagementMaxGroupKeysPerFabric()
        : ReadAttribute("max-group-keys-per-fabric")
    {
    }

    ~ReadGroupKeyManagementMaxGroupKeysPerFabric() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeMaxGroupKeysPerFabricWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.MaxGroupKeysPerFabric response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement MaxGroupKeysPerFabric read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementMaxGroupKeysPerFabric : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementMaxGroupKeysPerFabric()
        : SubscribeAttribute("max-group-keys-per-fabric")
    {
    }

    ~SubscribeAttributeGroupKeyManagementMaxGroupKeysPerFabric() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxGroupKeysPerFabricWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.MaxGroupKeysPerFabric response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadGroupKeyManagementGeneratedCommandList : public ReadAttribute {
public:
    ReadGroupKeyManagementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadGroupKeyManagementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeGroupKeyManagementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadGroupKeyManagementAcceptedCommandList : public ReadAttribute {
public:
    ReadGroupKeyManagementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadGroupKeyManagementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeGroupKeyManagementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadGroupKeyManagementAttributeList : public ReadAttribute {
public:
    ReadGroupKeyManagementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadGroupKeyManagementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeGroupKeyManagementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadGroupKeyManagementFeatureMap : public ReadAttribute {
public:
    ReadGroupKeyManagementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadGroupKeyManagementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeGroupKeyManagementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadGroupKeyManagementClusterRevision : public ReadAttribute {
public:
    ReadGroupKeyManagementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadGroupKeyManagementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeGroupKeyManagementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                     endpoint:endpointId
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster FixedLabel                                                  | 0x0040 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * LabelList                                                         | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute LabelList
 */
class ReadFixedLabelLabelList : public ReadAttribute {
public:
    ReadFixedLabelLabelList()
        : ReadAttribute("label-list")
    {
    }

    ~ReadFixedLabelLabelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeLabelListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.LabelList response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel LabelList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelLabelList : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelLabelList()
        : SubscribeAttribute("label-list")
    {
    }

    ~SubscribeAttributeFixedLabelLabelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLabelListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.LabelList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadFixedLabelGeneratedCommandList : public ReadAttribute {
public:
    ReadFixedLabelGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadFixedLabelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeFixedLabelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadFixedLabelAcceptedCommandList : public ReadAttribute {
public:
    ReadFixedLabelAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadFixedLabelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeFixedLabelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadFixedLabelAttributeList : public ReadAttribute {
public:
    ReadFixedLabelAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadFixedLabelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeFixedLabelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadFixedLabelFeatureMap : public ReadAttribute {
public:
    ReadFixedLabelFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadFixedLabelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeFixedLabelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadFixedLabelClusterRevision : public ReadAttribute {
public:
    ReadFixedLabelClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadFixedLabelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeFixedLabelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster UserLabel                                                   | 0x0041 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * LabelList                                                         | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute LabelList
 */
class ReadUserLabelLabelList : public ReadAttribute {
public:
    ReadUserLabelLabelList()
        : ReadAttribute("label-list")
    {
    }

    ~ReadUserLabelLabelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeLabelListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.LabelList response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel LabelList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUserLabelLabelList : public WriteAttribute {
public:
    WriteUserLabelLabelList()
        : WriteAttribute("label-list")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "label-list");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteUserLabelLabelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRUserLabelClusterLabelStruct * newElement_0;
                newElement_0 = [MTRUserLabelClusterLabelStruct new];
                newElement_0.label = [[NSString alloc] initWithBytes:entry_0.label.data()
                                                              length:entry_0.label.size()
                                                            encoding:NSUTF8StringEncoding];
                newElement_0.value = [[NSString alloc] initWithBytes:entry_0.value.data()
                                                              length:entry_0.value.size()
                                                            encoding:NSUTF8StringEncoding];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeLabelListWithValue:value
                                           params:params
                                completionHandler:^(NSError * _Nullable error) {
                                    if (error != nil) {
                                        LogNSError("UserLabel LabelList write Error", error);
                                    }
                                    SetCommandExitStatus(error);
                                }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::UserLabel::Structs::LabelStruct::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::UserLabel::Structs::LabelStruct::Type>> mComplex;
};

class SubscribeAttributeUserLabelLabelList : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelLabelList()
        : SubscribeAttribute("label-list")
    {
    }

    ~SubscribeAttributeUserLabelLabelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLabelListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.LabelList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadUserLabelGeneratedCommandList : public ReadAttribute {
public:
    ReadUserLabelGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadUserLabelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUserLabelGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeUserLabelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadUserLabelAcceptedCommandList : public ReadAttribute {
public:
    ReadUserLabelAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadUserLabelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUserLabelAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeUserLabelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadUserLabelAttributeList : public ReadAttribute {
public:
    ReadUserLabelAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadUserLabelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUserLabelAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeUserLabelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadUserLabelFeatureMap : public ReadAttribute {
public:
    ReadUserLabelFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadUserLabelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUserLabelFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeUserLabelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadUserLabelClusterRevision : public ReadAttribute {
public:
    ReadUserLabelClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadUserLabelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUserLabelClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeUserLabelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster BooleanState                                                | 0x0045 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * StateValue                                                        | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StateChange                                                       | 0x0000 |
\*----------------------------------------------------------------------------*/

/*
 * Attribute StateValue
 */
class ReadBooleanStateStateValue : public ReadAttribute {
public:
    ReadBooleanStateStateValue()
        : ReadAttribute("state-value")
    {
    }

    ~ReadBooleanStateStateValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeStateValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.StateValue response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState StateValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateStateValue : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateStateValue()
        : SubscribeAttribute("state-value")
    {
    }

    ~SubscribeAttributeBooleanStateStateValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeStateValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.StateValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBooleanStateGeneratedCommandList : public ReadAttribute {
public:
    ReadBooleanStateGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBooleanStateGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBooleanStateGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBooleanStateAcceptedCommandList : public ReadAttribute {
public:
    ReadBooleanStateAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBooleanStateAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBooleanStateAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBooleanStateAttributeList : public ReadAttribute {
public:
    ReadBooleanStateAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBooleanStateAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBooleanStateAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBooleanStateFeatureMap : public ReadAttribute {
public:
    ReadBooleanStateFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBooleanStateFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBooleanStateFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBooleanStateClusterRevision : public ReadAttribute {
public:
    ReadBooleanStateClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBooleanStateClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBooleanStateClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ModeSelect                                                  | 0x0050 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ChangeToMode                                                      |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Description                                                       | 0x0000 |
| * StandardNamespace                                                 | 0x0001 |
| * SupportedModes                                                    | 0x0002 |
| * CurrentMode                                                       | 0x0003 |
| * StartUpMode                                                       | 0x0004 |
| * OnMode                                                            | 0x0005 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ChangeToMode
 */
class ModeSelectChangeToMode : public ClusterCommand {
public:
    ModeSelectChangeToMode()
        : ClusterCommand("change-to-mode")
    {
        AddArgument("NewMode", 0, UINT8_MAX, &mRequest.newMode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint: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
                          completionHandler:^(NSError * _Nullable error) {
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ModeSelect::Commands::ChangeToMode::Type mRequest;
};

/*
 * Attribute Description
 */
class ReadModeSelectDescription : public ReadAttribute {
public:
    ReadModeSelectDescription()
        : ReadAttribute("description")
    {
    }

    ~ReadModeSelectDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeDescriptionWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.Description response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect Description read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectDescription : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectDescription()
        : SubscribeAttribute("description")
    {
    }

    ~SubscribeAttributeModeSelectDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDescriptionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.Description response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StandardNamespace
 */
class ReadModeSelectStandardNamespace : public ReadAttribute {
public:
    ReadModeSelectStandardNamespace()
        : ReadAttribute("standard-namespace")
    {
    }

    ~ReadModeSelectStandardNamespace() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeStandardNamespaceWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.StandardNamespace response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect StandardNamespace read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectStandardNamespace : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectStandardNamespace()
        : SubscribeAttribute("standard-namespace")
    {
    }

    ~SubscribeAttributeModeSelectStandardNamespace() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeStandardNamespaceWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.StandardNamespace response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedModes
 */
class ReadModeSelectSupportedModes : public ReadAttribute {
public:
    ReadModeSelectSupportedModes()
        : ReadAttribute("supported-modes")
    {
    }

    ~ReadModeSelectSupportedModes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeSupportedModesWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.SupportedModes response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect SupportedModes read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectSupportedModes : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectSupportedModes()
        : SubscribeAttribute("supported-modes")
    {
    }

    ~SubscribeAttributeModeSelectSupportedModes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSupportedModesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.SupportedModes response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentMode
 */
class ReadModeSelectCurrentMode : public ReadAttribute {
public:
    ReadModeSelectCurrentMode()
        : ReadAttribute("current-mode")
    {
    }

    ~ReadModeSelectCurrentMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeCurrentModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.CurrentMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect CurrentMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectCurrentMode : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectCurrentMode()
        : SubscribeAttribute("current-mode")
    {
    }

    ~SubscribeAttributeModeSelectCurrentMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.CurrentMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StartUpMode
 */
class ReadModeSelectStartUpMode : public ReadAttribute {
public:
    ReadModeSelectStartUpMode()
        : ReadAttribute("start-up-mode")
    {
    }

    ~ReadModeSelectStartUpMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeStartUpModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.StartUpMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect StartUpMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteModeSelectStartUpMode : public WriteAttribute {
public:
    WriteModeSelectStartUpMode()
        : WriteAttribute("start-up-mode")
    {
        AddArgument("attr-name", "start-up-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteModeSelectStartUpMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeStartUpModeWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("ModeSelect StartUpMode write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeModeSelectStartUpMode : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectStartUpMode()
        : SubscribeAttribute("start-up-mode")
    {
    }

    ~SubscribeAttributeModeSelectStartUpMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeStartUpModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.StartUpMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OnMode
 */
class ReadModeSelectOnMode : public ReadAttribute {
public:
    ReadModeSelectOnMode()
        : ReadAttribute("on-mode")
    {
    }

    ~ReadModeSelectOnMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeOnModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.OnMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect OnMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteModeSelectOnMode : public WriteAttribute {
public:
    WriteModeSelectOnMode()
        : WriteAttribute("on-mode")
    {
        AddArgument("attr-name", "on-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteModeSelectOnMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOnModeWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("ModeSelect OnMode write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeModeSelectOnMode : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectOnMode()
        : SubscribeAttribute("on-mode")
    {
    }

    ~SubscribeAttributeModeSelectOnMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOnModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.OnMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadModeSelectGeneratedCommandList : public ReadAttribute {
public:
    ReadModeSelectGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadModeSelectGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeModeSelectGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadModeSelectAcceptedCommandList : public ReadAttribute {
public:
    ReadModeSelectAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadModeSelectAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeModeSelectAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadModeSelectAttributeList : public ReadAttribute {
public:
    ReadModeSelectAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadModeSelectAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeModeSelectAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadModeSelectFeatureMap : public ReadAttribute {
public:
    ReadModeSelectFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadModeSelectFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeModeSelectFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadModeSelectClusterRevision : public ReadAttribute {
public:
    ReadModeSelectClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadModeSelectClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeModeSelectClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster DoorLock                                                    | 0x0101 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * LockDoor                                                          |   0x00 |
| * UnlockDoor                                                        |   0x01 |
| * UnlockWithTimeout                                                 |   0x03 |
| * SetWeekDaySchedule                                                |   0x0B |
| * GetWeekDaySchedule                                                |   0x0C |
| * ClearWeekDaySchedule                                              |   0x0D |
| * SetYearDaySchedule                                                |   0x0E |
| * GetYearDaySchedule                                                |   0x0F |
| * ClearYearDaySchedule                                              |   0x10 |
| * SetHolidaySchedule                                                |   0x11 |
| * GetHolidaySchedule                                                |   0x12 |
| * ClearHolidaySchedule                                              |   0x13 |
| * SetUser                                                           |   0x1A |
| * GetUser                                                           |   0x1B |
| * ClearUser                                                         |   0x1D |
| * SetCredential                                                     |   0x22 |
| * GetCredentialStatus                                               |   0x24 |
| * ClearCredential                                                   |   0x26 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * LockState                                                         | 0x0000 |
| * LockType                                                          | 0x0001 |
| * ActuatorEnabled                                                   | 0x0002 |
| * DoorState                                                         | 0x0003 |
| * DoorOpenEvents                                                    | 0x0004 |
| * DoorClosedEvents                                                  | 0x0005 |
| * OpenPeriod                                                        | 0x0006 |
| * NumberOfTotalUsersSupported                                       | 0x0011 |
| * NumberOfPINUsersSupported                                         | 0x0012 |
| * NumberOfRFIDUsersSupported                                        | 0x0013 |
| * NumberOfWeekDaySchedulesSupportedPerUser                          | 0x0014 |
| * NumberOfYearDaySchedulesSupportedPerUser                          | 0x0015 |
| * NumberOfHolidaySchedulesSupported                                 | 0x0016 |
| * MaxPINCodeLength                                                  | 0x0017 |
| * MinPINCodeLength                                                  | 0x0018 |
| * MaxRFIDCodeLength                                                 | 0x0019 |
| * MinRFIDCodeLength                                                 | 0x001A |
| * CredentialRulesSupport                                            | 0x001B |
| * NumberOfCredentialsSupportedPerUser                               | 0x001C |
| * Language                                                          | 0x0021 |
| * LEDSettings                                                       | 0x0022 |
| * AutoRelockTime                                                    | 0x0023 |
| * SoundVolume                                                       | 0x0024 |
| * OperatingMode                                                     | 0x0025 |
| * SupportedOperatingModes                                           | 0x0026 |
| * DefaultConfigurationRegister                                      | 0x0027 |
| * EnableLocalProgramming                                            | 0x0028 |
| * EnableOneTouchLocking                                             | 0x0029 |
| * EnableInsideStatusLED                                             | 0x002A |
| * EnablePrivacyModeButton                                           | 0x002B |
| * LocalProgrammingFeatures                                          | 0x002C |
| * WrongCodeEntryLimit                                               | 0x0030 |
| * UserCodeTemporaryDisableTime                                      | 0x0031 |
| * SendPINOverTheAir                                                 | 0x0032 |
| * RequirePINforRemoteOperation                                      | 0x0033 |
| * ExpiringUserTimeout                                               | 0x0035 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * DoorLockAlarm                                                     | 0x0000 |
| * DoorStateChange                                                   | 0x0001 |
| * LockOperation                                                     | 0x0002 |
| * LockOperationError                                                | 0x0003 |
| * LockUserChange                                                    | 0x0004 |
\*----------------------------------------------------------------------------*/

/*
 * Command LockDoor
 */
class DoorLockLockDoor : public ClusterCommand {
public:
    DoorLockLockDoor()
        : ClusterCommand("lock-door")
    {
        AddArgument("PinCode", &mRequest.pinCode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                      completionHandler:^(NSError * _Nullable error) {
                          responsesNeeded--;
                          if (error != nil) {
                              mError = error;
                              LogNSError("Error", error);
                          }
                          if (responsesNeeded == 0) {
                              SetCommandExitStatus(mError);
                          }
                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::LockDoor::Type mRequest;
};

/*
 * Command UnlockDoor
 */
class DoorLockUnlockDoor : public ClusterCommand {
public:
    DoorLockUnlockDoor()
        : ClusterCommand("unlock-door")
    {
        AddArgument("PinCode", &mRequest.pinCode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                        completionHandler:^(NSError * _Nullable error) {
                            responsesNeeded--;
                            if (error != nil) {
                                mError = error;
                                LogNSError("Error", error);
                            }
                            if (responsesNeeded == 0) {
                                SetCommandExitStatus(mError);
                            }
                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::UnlockDoor::Type mRequest;
};

/*
 * Command UnlockWithTimeout
 */
class DoorLockUnlockWithTimeout : public ClusterCommand {
public:
    DoorLockUnlockWithTimeout()
        : ClusterCommand("unlock-with-timeout")
    {
        AddArgument("Timeout", 0, UINT16_MAX, &mRequest.timeout);
        AddArgument("PinCode", &mRequest.pinCode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                               completionHandler:^(NSError * _Nullable error) {
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::UnlockWithTimeout::Type mRequest;
};

/*
 * Command SetWeekDaySchedule
 */
class DoorLockSetWeekDaySchedule : public ClusterCommand {
public:
    DoorLockSetWeekDaySchedule()
        : ClusterCommand("set-week-day-schedule")
    {
        AddArgument("WeekDayIndex", 0, UINT8_MAX, &mRequest.weekDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        AddArgument("DaysMask", 0, UINT8_MAX, &mRequest.daysMask);
        AddArgument("StartHour", 0, UINT8_MAX, &mRequest.startHour);
        AddArgument("StartMinute", 0, UINT8_MAX, &mRequest.startMinute);
        AddArgument("EndHour", 0, UINT8_MAX, &mRequest.endHour);
        AddArgument("EndMinute", 0, UINT8_MAX, &mRequest.endMinute);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                                completionHandler:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::SetWeekDaySchedule::Type mRequest;
};

/*
 * Command GetWeekDaySchedule
 */
class DoorLockGetWeekDaySchedule : public ClusterCommand {
public:
    DoorLockGetWeekDaySchedule()
        : ClusterCommand("get-week-day-schedule")
    {
        AddArgument("WeekDayIndex", 0, UINT8_MAX, &mRequest.weekDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                                completionHandler:^(MTRDoorLockClusterGetWeekDayScheduleResponseParams * _Nullable values,
                                    NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::GetWeekDaySchedule::Type mRequest;
};

/*
 * Command ClearWeekDaySchedule
 */
class DoorLockClearWeekDaySchedule : public ClusterCommand {
public:
    DoorLockClearWeekDaySchedule()
        : ClusterCommand("clear-week-day-schedule")
    {
        AddArgument("WeekDayIndex", 0, UINT8_MAX, &mRequest.weekDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                                  completionHandler:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::ClearWeekDaySchedule::Type mRequest;
};

/*
 * Command SetYearDaySchedule
 */
class DoorLockSetYearDaySchedule : public ClusterCommand {
public:
    DoorLockSetYearDaySchedule()
        : ClusterCommand("set-year-day-schedule")
    {
        AddArgument("YearDayIndex", 0, UINT8_MAX, &mRequest.yearDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        AddArgument("LocalStartTime", 0, UINT32_MAX, &mRequest.localStartTime);
        AddArgument("LocalEndTime", 0, UINT32_MAX, &mRequest.localEndTime);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                                completionHandler:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::SetYearDaySchedule::Type mRequest;
};

/*
 * Command GetYearDaySchedule
 */
class DoorLockGetYearDaySchedule : public ClusterCommand {
public:
    DoorLockGetYearDaySchedule()
        : ClusterCommand("get-year-day-schedule")
    {
        AddArgument("YearDayIndex", 0, UINT8_MAX, &mRequest.yearDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                                completionHandler:^(MTRDoorLockClusterGetYearDayScheduleResponseParams * _Nullable values,
                                    NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::GetYearDaySchedule::Type mRequest;
};

/*
 * Command ClearYearDaySchedule
 */
class DoorLockClearYearDaySchedule : public ClusterCommand {
public:
    DoorLockClearYearDaySchedule()
        : ClusterCommand("clear-year-day-schedule")
    {
        AddArgument("YearDayIndex", 0, UINT8_MAX, &mRequest.yearDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                                  completionHandler:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::ClearYearDaySchedule::Type mRequest;
};

/*
 * Command SetHolidaySchedule
 */
class DoorLockSetHolidaySchedule : public ClusterCommand {
public:
    DoorLockSetHolidaySchedule()
        : ClusterCommand("set-holiday-schedule")
    {
        AddArgument("HolidayIndex", 0, UINT8_MAX, &mRequest.holidayIndex);
        AddArgument("LocalStartTime", 0, UINT32_MAX, &mRequest.localStartTime);
        AddArgument("LocalEndTime", 0, UINT32_MAX, &mRequest.localEndTime);
        AddArgument("OperatingMode", 0, UINT8_MAX, &mRequest.operatingMode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                                completionHandler:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::SetHolidaySchedule::Type mRequest;
};

/*
 * Command GetHolidaySchedule
 */
class DoorLockGetHolidaySchedule : public ClusterCommand {
public:
    DoorLockGetHolidaySchedule()
        : ClusterCommand("get-holiday-schedule")
    {
        AddArgument("HolidayIndex", 0, UINT8_MAX, &mRequest.holidayIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                                completionHandler:^(MTRDoorLockClusterGetHolidayScheduleResponseParams * _Nullable values,
                                    NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::GetHolidaySchedule::Type mRequest;
};

/*
 * Command ClearHolidaySchedule
 */
class DoorLockClearHolidaySchedule : public ClusterCommand {
public:
    DoorLockClearHolidaySchedule()
        : ClusterCommand("clear-holiday-schedule")
    {
        AddArgument("HolidayIndex", 0, UINT8_MAX, &mRequest.holidayIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                                  completionHandler:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::ClearHolidaySchedule::Type mRequest;
};

/*
 * Command SetUser
 */
class DoorLockSetUser : public ClusterCommand {
public:
    DoorLockSetUser()
        : ClusterCommand("set-user")
    {
        AddArgument("OperationType", 0, UINT8_MAX, &mRequest.operationType);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        AddArgument("UserName", &mRequest.userName);
        AddArgument("UserUniqueId", 0, UINT32_MAX, &mRequest.userUniqueId);
        AddArgument("UserStatus", 0, UINT8_MAX, &mRequest.userStatus);
        AddArgument("UserType", 0, UINT8_MAX, &mRequest.userType);
        AddArgument("CredentialRule", 0, UINT8_MAX, &mRequest.credentialRule);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                     completionHandler:^(NSError * _Nullable error) {
                         responsesNeeded--;
                         if (error != nil) {
                             mError = error;
                             LogNSError("Error", error);
                         }
                         if (responsesNeeded == 0) {
                             SetCommandExitStatus(mError);
                         }
                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::SetUser::Type mRequest;
};

/*
 * Command GetUser
 */
class DoorLockGetUser : public ClusterCommand {
public:
    DoorLockGetUser()
        : ClusterCommand("get-user")
    {
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                     completionHandler:^(MTRDoorLockClusterGetUserResponseParams * _Nullable values, NSError * _Nullable error) {
                         NSLog(@"Values: %@", values);
                         responsesNeeded--;
                         if (error != nil) {
                             mError = error;
                             LogNSError("Error", error);
                         }
                         if (responsesNeeded == 0) {
                             SetCommandExitStatus(mError);
                         }
                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::GetUser::Type mRequest;
};

/*
 * Command ClearUser
 */
class DoorLockClearUser : public ClusterCommand {
public:
    DoorLockClearUser()
        : ClusterCommand("clear-user")
    {
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000001D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint: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
                       completionHandler:^(NSError * _Nullable error) {
                           responsesNeeded--;
                           if (error != nil) {
                               mError = error;
                               LogNSError("Error", error);
                           }
                           if (responsesNeeded == 0) {
                               SetCommandExitStatus(mError);
                           }
                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::ClearUser::Type mRequest;
};

/*
 * Command SetCredential
 */
class DoorLockSetCredential : public ClusterCommand {
public:
    DoorLockSetCredential()
        : ClusterCommand("set-credential")
        , mComplex_Credential(&mRequest.credential)
    {
        AddArgument("OperationType", 0, UINT8_MAX, &mRequest.operationType);
        AddArgument("Credential", &mComplex_Credential);
        AddArgument("CredentialData", &mRequest.credentialData);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        AddArgument("UserStatus", 0, UINT8_MAX, &mRequest.userStatus);
        AddArgument("UserType", 0, UINT8_MAX, &mRequest.userType);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterSetCredentialParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.operationType = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.operationType)];
        params.credential = [MTRDoorLockClusterDlCredential new];
        params.credential.credentialType =
            [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.credential.credentialType)];
        params.credential.credentialIndex = [NSNumber numberWithUnsignedShort:mRequest.credential.credentialIndex];
        params.credentialData = [NSData dataWithBytes:mRequest.credentialData.data() length:mRequest.credentialData.size()];
        if (mRequest.userIndex.IsNull()) {
            params.userIndex = nil;
        } else {
            params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex.Value()];
        }
        if (mRequest.userStatus.IsNull()) {
            params.userStatus = nil;
        } else {
            params.userStatus = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.userStatus.Value())];
        }
        if (mRequest.userType.IsNull()) {
            params.userType = nil;
        } else {
            params.userType = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.userType.Value())];
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster setCredentialWithParams:params
                           completionHandler:^(
                               MTRDoorLockClusterSetCredentialResponseParams * _Nullable values, NSError * _Nullable error) {
                               NSLog(@"Values: %@", values);
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::SetCredential::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::DoorLock::Structs::DlCredential::Type> mComplex_Credential;
};

/*
 * Command GetCredentialStatus
 */
class DoorLockGetCredentialStatus : public ClusterCommand {
public:
    DoorLockGetCredentialStatus()
        : ClusterCommand("get-credential-status")
        , mComplex_Credential(&mRequest.credential)
    {
        AddArgument("Credential", &mComplex_Credential);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterGetCredentialStatusParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.credential = [MTRDoorLockClusterDlCredential new];
        params.credential.credentialType =
            [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.credential.credentialType)];
        params.credential.credentialIndex = [NSNumber numberWithUnsignedShort:mRequest.credential.credentialIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getCredentialStatusWithParams:params
                                 completionHandler:^(MTRDoorLockClusterGetCredentialStatusResponseParams * _Nullable values,
                                     NSError * _Nullable error) {
                                     NSLog(@"Values: %@", values);
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::DoorLock::Structs::DlCredential::Type> mComplex_Credential;
};

/*
 * Command ClearCredential
 */
class DoorLockClearCredential : public ClusterCommand {
public:
    DoorLockClearCredential()
        : ClusterCommand("clear-credential")
        , mComplex_Credential(&mRequest.credential)
    {
        AddArgument("Credential", &mComplex_Credential);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterClearCredentialParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.credential.IsNull()) {
            params.credential = nil;
        } else {
            params.credential = [MTRDoorLockClusterDlCredential new];
            params.credential.credentialType =
                [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.credential.Value().credentialType)];
            params.credential.credentialIndex = [NSNumber numberWithUnsignedShort:mRequest.credential.Value().credentialIndex];
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster clearCredentialWithParams:params
                             completionHandler:^(NSError * _Nullable error) {
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::ClearCredential::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::Nullable<chip::app::Clusters::DoorLock::Structs::DlCredential::Type>>
        mComplex_Credential;
};

/*
 * Attribute LockState
 */
class ReadDoorLockLockState : public ReadAttribute {
public:
    ReadDoorLockLockState()
        : ReadAttribute("lock-state")
    {
    }

    ~ReadDoorLockLockState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeLockStateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.LockState response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock LockState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockLockState : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockLockState()
        : SubscribeAttribute("lock-state")
    {
    }

    ~SubscribeAttributeDoorLockLockState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLockStateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.LockState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LockType
 */
class ReadDoorLockLockType : public ReadAttribute {
public:
    ReadDoorLockLockType()
        : ReadAttribute("lock-type")
    {
    }

    ~ReadDoorLockLockType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeLockTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.LockType response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock LockType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockLockType : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockLockType()
        : SubscribeAttribute("lock-type")
    {
    }

    ~SubscribeAttributeDoorLockLockType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLockTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.LockType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActuatorEnabled
 */
class ReadDoorLockActuatorEnabled : public ReadAttribute {
public:
    ReadDoorLockActuatorEnabled()
        : ReadAttribute("actuator-enabled")
    {
    }

    ~ReadDoorLockActuatorEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeActuatorEnabledWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.ActuatorEnabled response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock ActuatorEnabled read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockActuatorEnabled : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockActuatorEnabled()
        : SubscribeAttribute("actuator-enabled")
    {
    }

    ~SubscribeAttributeDoorLockActuatorEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActuatorEnabledWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.ActuatorEnabled response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DoorState
 */
class ReadDoorLockDoorState : public ReadAttribute {
public:
    ReadDoorLockDoorState()
        : ReadAttribute("door-state")
    {
    }

    ~ReadDoorLockDoorState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeDoorStateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.DoorState response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock DoorState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockDoorState : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockDoorState()
        : SubscribeAttribute("door-state")
    {
    }

    ~SubscribeAttributeDoorLockDoorState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDoorStateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.DoorState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DoorOpenEvents
 */
class ReadDoorLockDoorOpenEvents : public ReadAttribute {
public:
    ReadDoorLockDoorOpenEvents()
        : ReadAttribute("door-open-events")
    {
    }

    ~ReadDoorLockDoorOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeDoorOpenEventsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.DoorOpenEvents response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock DoorOpenEvents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockDoorOpenEvents : public WriteAttribute {
public:
    WriteDoorLockDoorOpenEvents()
        : WriteAttribute("door-open-events")
    {
        AddArgument("attr-name", "door-open-events");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockDoorOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeDoorOpenEventsWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("DoorLock DoorOpenEvents write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeDoorLockDoorOpenEvents : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockDoorOpenEvents()
        : SubscribeAttribute("door-open-events")
    {
    }

    ~SubscribeAttributeDoorLockDoorOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDoorOpenEventsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.DoorOpenEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DoorClosedEvents
 */
class ReadDoorLockDoorClosedEvents : public ReadAttribute {
public:
    ReadDoorLockDoorClosedEvents()
        : ReadAttribute("door-closed-events")
    {
    }

    ~ReadDoorLockDoorClosedEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeDoorClosedEventsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.DoorClosedEvents response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock DoorClosedEvents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockDoorClosedEvents : public WriteAttribute {
public:
    WriteDoorLockDoorClosedEvents()
        : WriteAttribute("door-closed-events")
    {
        AddArgument("attr-name", "door-closed-events");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockDoorClosedEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeDoorClosedEventsWithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("DoorLock DoorClosedEvents write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeDoorLockDoorClosedEvents : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockDoorClosedEvents()
        : SubscribeAttribute("door-closed-events")
    {
    }

    ~SubscribeAttributeDoorLockDoorClosedEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDoorClosedEventsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.DoorClosedEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OpenPeriod
 */
class ReadDoorLockOpenPeriod : public ReadAttribute {
public:
    ReadDoorLockOpenPeriod()
        : ReadAttribute("open-period")
    {
    }

    ~ReadDoorLockOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeOpenPeriodWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.OpenPeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock OpenPeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockOpenPeriod : public WriteAttribute {
public:
    WriteDoorLockOpenPeriod()
        : WriteAttribute("open-period")
    {
        AddArgument("attr-name", "open-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeOpenPeriodWithValue:value
                                            params:params
                                 completionHandler:^(NSError * _Nullable error) {
                                     if (error != nil) {
                                         LogNSError("DoorLock OpenPeriod write Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeDoorLockOpenPeriod : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockOpenPeriod()
        : SubscribeAttribute("open-period")
    {
    }

    ~SubscribeAttributeDoorLockOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOpenPeriodWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.OpenPeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfTotalUsersSupported
 */
class ReadDoorLockNumberOfTotalUsersSupported : public ReadAttribute {
public:
    ReadDoorLockNumberOfTotalUsersSupported()
        : ReadAttribute("number-of-total-users-supported")
    {
    }

    ~ReadDoorLockNumberOfTotalUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster
            readAttributeNumberOfTotalUsersSupportedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfTotalUsersSupported response %@", [value description]);
                if (error != nil) {
                    LogNSError("DoorLock NumberOfTotalUsersSupported read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfTotalUsersSupported : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfTotalUsersSupported()
        : SubscribeAttribute("number-of-total-users-supported")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfTotalUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfTotalUsersSupportedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfTotalUsersSupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfPINUsersSupported
 */
class ReadDoorLockNumberOfPINUsersSupported : public ReadAttribute {
public:
    ReadDoorLockNumberOfPINUsersSupported()
        : ReadAttribute("number-of-pinusers-supported")
    {
    }

    ~ReadDoorLockNumberOfPINUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster
            readAttributeNumberOfPINUsersSupportedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfPINUsersSupported response %@", [value description]);
                if (error != nil) {
                    LogNSError("DoorLock NumberOfPINUsersSupported read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfPINUsersSupported : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfPINUsersSupported()
        : SubscribeAttribute("number-of-pinusers-supported")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfPINUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfPINUsersSupportedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfPINUsersSupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfRFIDUsersSupported
 */
class ReadDoorLockNumberOfRFIDUsersSupported : public ReadAttribute {
public:
    ReadDoorLockNumberOfRFIDUsersSupported()
        : ReadAttribute("number-of-rfidusers-supported")
    {
    }

    ~ReadDoorLockNumberOfRFIDUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster
            readAttributeNumberOfRFIDUsersSupportedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfRFIDUsersSupported response %@", [value description]);
                if (error != nil) {
                    LogNSError("DoorLock NumberOfRFIDUsersSupported read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfRFIDUsersSupported : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfRFIDUsersSupported()
        : SubscribeAttribute("number-of-rfidusers-supported")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfRFIDUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfRFIDUsersSupportedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfRFIDUsersSupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfWeekDaySchedulesSupportedPerUser
 */
class ReadDoorLockNumberOfWeekDaySchedulesSupportedPerUser : public ReadAttribute {
public:
    ReadDoorLockNumberOfWeekDaySchedulesSupportedPerUser()
        : ReadAttribute("number-of-week-day-schedules-supported-per-user")
    {
    }

    ~ReadDoorLockNumberOfWeekDaySchedulesSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeNumberOfWeekDaySchedulesSupportedPerUserWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.NumberOfWeekDaySchedulesSupportedPerUser response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock NumberOfWeekDaySchedulesSupportedPerUser read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfWeekDaySchedulesSupportedPerUser : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfWeekDaySchedulesSupportedPerUser()
        : SubscribeAttribute("number-of-week-day-schedules-supported-per-user")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfWeekDaySchedulesSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster
            subscribeAttributeNumberOfWeekDaySchedulesSupportedPerUserWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfWeekDaySchedulesSupportedPerUser response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfYearDaySchedulesSupportedPerUser
 */
class ReadDoorLockNumberOfYearDaySchedulesSupportedPerUser : public ReadAttribute {
public:
    ReadDoorLockNumberOfYearDaySchedulesSupportedPerUser()
        : ReadAttribute("number-of-year-day-schedules-supported-per-user")
    {
    }

    ~ReadDoorLockNumberOfYearDaySchedulesSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeNumberOfYearDaySchedulesSupportedPerUserWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.NumberOfYearDaySchedulesSupportedPerUser response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock NumberOfYearDaySchedulesSupportedPerUser read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfYearDaySchedulesSupportedPerUser : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfYearDaySchedulesSupportedPerUser()
        : SubscribeAttribute("number-of-year-day-schedules-supported-per-user")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfYearDaySchedulesSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster
            subscribeAttributeNumberOfYearDaySchedulesSupportedPerUserWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfYearDaySchedulesSupportedPerUser response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfHolidaySchedulesSupported
 */
class ReadDoorLockNumberOfHolidaySchedulesSupported : public ReadAttribute {
public:
    ReadDoorLockNumberOfHolidaySchedulesSupported()
        : ReadAttribute("number-of-holiday-schedules-supported")
    {
    }

    ~ReadDoorLockNumberOfHolidaySchedulesSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeNumberOfHolidaySchedulesSupportedWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.NumberOfHolidaySchedulesSupported response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock NumberOfHolidaySchedulesSupported read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfHolidaySchedulesSupported : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfHolidaySchedulesSupported()
        : SubscribeAttribute("number-of-holiday-schedules-supported")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfHolidaySchedulesSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfHolidaySchedulesSupportedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfHolidaySchedulesSupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxPINCodeLength
 */
class ReadDoorLockMaxPINCodeLength : public ReadAttribute {
public:
    ReadDoorLockMaxPINCodeLength()
        : ReadAttribute("max-pincode-length")
    {
    }

    ~ReadDoorLockMaxPINCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeMaxPINCodeLengthWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.MaxPINCodeLength response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock MaxPINCodeLength read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockMaxPINCodeLength : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockMaxPINCodeLength()
        : SubscribeAttribute("max-pincode-length")
    {
    }

    ~SubscribeAttributeDoorLockMaxPINCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxPINCodeLengthWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.MaxPINCodeLength response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinPINCodeLength
 */
class ReadDoorLockMinPINCodeLength : public ReadAttribute {
public:
    ReadDoorLockMinPINCodeLength()
        : ReadAttribute("min-pincode-length")
    {
    }

    ~ReadDoorLockMinPINCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeMinPINCodeLengthWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.MinPINCodeLength response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock MinPINCodeLength read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockMinPINCodeLength : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockMinPINCodeLength()
        : SubscribeAttribute("min-pincode-length")
    {
    }

    ~SubscribeAttributeDoorLockMinPINCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinPINCodeLengthWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.MinPINCodeLength response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxRFIDCodeLength
 */
class ReadDoorLockMaxRFIDCodeLength : public ReadAttribute {
public:
    ReadDoorLockMaxRFIDCodeLength()
        : ReadAttribute("max-rfidcode-length")
    {
    }

    ~ReadDoorLockMaxRFIDCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeMaxRFIDCodeLengthWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.MaxRFIDCodeLength response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock MaxRFIDCodeLength read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockMaxRFIDCodeLength : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockMaxRFIDCodeLength()
        : SubscribeAttribute("max-rfidcode-length")
    {
    }

    ~SubscribeAttributeDoorLockMaxRFIDCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxRFIDCodeLengthWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.MaxRFIDCodeLength response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinRFIDCodeLength
 */
class ReadDoorLockMinRFIDCodeLength : public ReadAttribute {
public:
    ReadDoorLockMinRFIDCodeLength()
        : ReadAttribute("min-rfidcode-length")
    {
    }

    ~ReadDoorLockMinRFIDCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeMinRFIDCodeLengthWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.MinRFIDCodeLength response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock MinRFIDCodeLength read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockMinRFIDCodeLength : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockMinRFIDCodeLength()
        : SubscribeAttribute("min-rfidcode-length")
    {
    }

    ~SubscribeAttributeDoorLockMinRFIDCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinRFIDCodeLengthWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.MinRFIDCodeLength response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CredentialRulesSupport
 */
class ReadDoorLockCredentialRulesSupport : public ReadAttribute {
public:
    ReadDoorLockCredentialRulesSupport()
        : ReadAttribute("credential-rules-support")
    {
    }

    ~ReadDoorLockCredentialRulesSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeCredentialRulesSupportWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.CredentialRulesSupport response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock CredentialRulesSupport read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockCredentialRulesSupport : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockCredentialRulesSupport()
        : SubscribeAttribute("credential-rules-support")
    {
    }

    ~SubscribeAttributeDoorLockCredentialRulesSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCredentialRulesSupportWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.CredentialRulesSupport response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfCredentialsSupportedPerUser
 */
class ReadDoorLockNumberOfCredentialsSupportedPerUser : public ReadAttribute {
public:
    ReadDoorLockNumberOfCredentialsSupportedPerUser()
        : ReadAttribute("number-of-credentials-supported-per-user")
    {
    }

    ~ReadDoorLockNumberOfCredentialsSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeNumberOfCredentialsSupportedPerUserWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.NumberOfCredentialsSupportedPerUser response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock NumberOfCredentialsSupportedPerUser read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfCredentialsSupportedPerUser : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfCredentialsSupportedPerUser()
        : SubscribeAttribute("number-of-credentials-supported-per-user")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfCredentialsSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfCredentialsSupportedPerUserWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfCredentialsSupportedPerUser response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Language
 */
class ReadDoorLockLanguage : public ReadAttribute {
public:
    ReadDoorLockLanguage()
        : ReadAttribute("language")
    {
    }

    ~ReadDoorLockLanguage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeLanguageWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.Language response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock Language read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockLanguage : public WriteAttribute {
public:
    WriteDoorLockLanguage()
        : WriteAttribute("language")
    {
        AddArgument("attr-name", "language");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockLanguage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeLanguageWithValue:value
                                          params:params
                               completionHandler:^(NSError * _Nullable error) {
                                   if (error != nil) {
                                       LogNSError("DoorLock Language write Error", error);
                                   }
                                   SetCommandExitStatus(error);
                               }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeDoorLockLanguage : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockLanguage()
        : SubscribeAttribute("language")
    {
    }

    ~SubscribeAttributeDoorLockLanguage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLanguageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.Language response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LEDSettings
 */
class ReadDoorLockLEDSettings : public ReadAttribute {
public:
    ReadDoorLockLEDSettings()
        : ReadAttribute("ledsettings")
    {
    }

    ~ReadDoorLockLEDSettings() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeLEDSettingsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.LEDSettings response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock LEDSettings read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockLEDSettings : public WriteAttribute {
public:
    WriteDoorLockLEDSettings()
        : WriteAttribute("ledsettings")
    {
        AddArgument("attr-name", "ledsettings");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockLEDSettings() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeLEDSettingsWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("DoorLock LEDSettings write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockLEDSettings : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockLEDSettings()
        : SubscribeAttribute("ledsettings")
    {
    }

    ~SubscribeAttributeDoorLockLEDSettings() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLEDSettingsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.LEDSettings response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AutoRelockTime
 */
class ReadDoorLockAutoRelockTime : public ReadAttribute {
public:
    ReadDoorLockAutoRelockTime()
        : ReadAttribute("auto-relock-time")
    {
    }

    ~ReadDoorLockAutoRelockTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000023) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeAutoRelockTimeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.AutoRelockTime response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock AutoRelockTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockAutoRelockTime : public WriteAttribute {
public:
    WriteDoorLockAutoRelockTime()
        : WriteAttribute("auto-relock-time")
    {
        AddArgument("attr-name", "auto-relock-time");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockAutoRelockTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeAutoRelockTimeWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("DoorLock AutoRelockTime write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeDoorLockAutoRelockTime : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockAutoRelockTime()
        : SubscribeAttribute("auto-relock-time")
    {
    }

    ~SubscribeAttributeDoorLockAutoRelockTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAutoRelockTimeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.AutoRelockTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoundVolume
 */
class ReadDoorLockSoundVolume : public ReadAttribute {
public:
    ReadDoorLockSoundVolume()
        : ReadAttribute("sound-volume")
    {
    }

    ~ReadDoorLockSoundVolume() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeSoundVolumeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.SoundVolume response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock SoundVolume read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockSoundVolume : public WriteAttribute {
public:
    WriteDoorLockSoundVolume()
        : WriteAttribute("sound-volume")
    {
        AddArgument("attr-name", "sound-volume");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockSoundVolume() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeSoundVolumeWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("DoorLock SoundVolume write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockSoundVolume : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockSoundVolume()
        : SubscribeAttribute("sound-volume")
    {
    }

    ~SubscribeAttributeDoorLockSoundVolume() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSoundVolumeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.SoundVolume response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OperatingMode
 */
class ReadDoorLockOperatingMode : public ReadAttribute {
public:
    ReadDoorLockOperatingMode()
        : ReadAttribute("operating-mode")
    {
    }

    ~ReadDoorLockOperatingMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeOperatingModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.OperatingMode response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock OperatingMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockOperatingMode : public WriteAttribute {
public:
    WriteDoorLockOperatingMode()
        : WriteAttribute("operating-mode")
    {
        AddArgument("attr-name", "operating-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockOperatingMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOperatingModeWithValue:value
                                               params:params
                                    completionHandler:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("DoorLock OperatingMode write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockOperatingMode : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockOperatingMode()
        : SubscribeAttribute("operating-mode")
    {
    }

    ~SubscribeAttributeDoorLockOperatingMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOperatingModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.OperatingMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedOperatingModes
 */
class ReadDoorLockSupportedOperatingModes : public ReadAttribute {
public:
    ReadDoorLockSupportedOperatingModes()
        : ReadAttribute("supported-operating-modes")
    {
    }

    ~ReadDoorLockSupportedOperatingModes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster
            readAttributeSupportedOperatingModesWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.SupportedOperatingModes response %@", [value description]);
                if (error != nil) {
                    LogNSError("DoorLock SupportedOperatingModes read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockSupportedOperatingModes : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockSupportedOperatingModes()
        : SubscribeAttribute("supported-operating-modes")
    {
    }

    ~SubscribeAttributeDoorLockSupportedOperatingModes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSupportedOperatingModesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.SupportedOperatingModes response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DefaultConfigurationRegister
 */
class ReadDoorLockDefaultConfigurationRegister : public ReadAttribute {
public:
    ReadDoorLockDefaultConfigurationRegister()
        : ReadAttribute("default-configuration-register")
    {
    }

    ~ReadDoorLockDefaultConfigurationRegister() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000027) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeDefaultConfigurationRegisterWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.DefaultConfigurationRegister response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock DefaultConfigurationRegister read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockDefaultConfigurationRegister : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockDefaultConfigurationRegister()
        : SubscribeAttribute("default-configuration-register")
    {
    }

    ~SubscribeAttributeDoorLockDefaultConfigurationRegister() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDefaultConfigurationRegisterWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.DefaultConfigurationRegister response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnableLocalProgramming
 */
class ReadDoorLockEnableLocalProgramming : public ReadAttribute {
public:
    ReadDoorLockEnableLocalProgramming()
        : ReadAttribute("enable-local-programming")
    {
    }

    ~ReadDoorLockEnableLocalProgramming() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000028) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeEnableLocalProgrammingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.EnableLocalProgramming response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock EnableLocalProgramming read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockEnableLocalProgramming : public WriteAttribute {
public:
    WriteDoorLockEnableLocalProgramming()
        : WriteAttribute("enable-local-programming")
    {
        AddArgument("attr-name", "enable-local-programming");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockEnableLocalProgramming() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeEnableLocalProgrammingWithValue:value
                                                        params:params
                                             completionHandler:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("DoorLock EnableLocalProgramming write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockEnableLocalProgramming : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockEnableLocalProgramming()
        : SubscribeAttribute("enable-local-programming")
    {
    }

    ~SubscribeAttributeDoorLockEnableLocalProgramming() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEnableLocalProgrammingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.EnableLocalProgramming response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnableOneTouchLocking
 */
class ReadDoorLockEnableOneTouchLocking : public ReadAttribute {
public:
    ReadDoorLockEnableOneTouchLocking()
        : ReadAttribute("enable-one-touch-locking")
    {
    }

    ~ReadDoorLockEnableOneTouchLocking() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeEnableOneTouchLockingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.EnableOneTouchLocking response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock EnableOneTouchLocking read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockEnableOneTouchLocking : public WriteAttribute {
public:
    WriteDoorLockEnableOneTouchLocking()
        : WriteAttribute("enable-one-touch-locking")
    {
        AddArgument("attr-name", "enable-one-touch-locking");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockEnableOneTouchLocking() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeEnableOneTouchLockingWithValue:value
                                                       params:params
                                            completionHandler:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("DoorLock EnableOneTouchLocking write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockEnableOneTouchLocking : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockEnableOneTouchLocking()
        : SubscribeAttribute("enable-one-touch-locking")
    {
    }

    ~SubscribeAttributeDoorLockEnableOneTouchLocking() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEnableOneTouchLockingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.EnableOneTouchLocking response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnableInsideStatusLED
 */
class ReadDoorLockEnableInsideStatusLED : public ReadAttribute {
public:
    ReadDoorLockEnableInsideStatusLED()
        : ReadAttribute("enable-inside-status-led")
    {
    }

    ~ReadDoorLockEnableInsideStatusLED() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000002A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeEnableInsideStatusLEDWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.EnableInsideStatusLED response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock EnableInsideStatusLED read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockEnableInsideStatusLED : public WriteAttribute {
public:
    WriteDoorLockEnableInsideStatusLED()
        : WriteAttribute("enable-inside-status-led")
    {
        AddArgument("attr-name", "enable-inside-status-led");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockEnableInsideStatusLED() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeEnableInsideStatusLEDWithValue:value
                                                       params:params
                                            completionHandler:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("DoorLock EnableInsideStatusLED write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockEnableInsideStatusLED : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockEnableInsideStatusLED()
        : SubscribeAttribute("enable-inside-status-led")
    {
    }

    ~SubscribeAttributeDoorLockEnableInsideStatusLED() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEnableInsideStatusLEDWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.EnableInsideStatusLED response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnablePrivacyModeButton
 */
class ReadDoorLockEnablePrivacyModeButton : public ReadAttribute {
public:
    ReadDoorLockEnablePrivacyModeButton()
        : ReadAttribute("enable-privacy-mode-button")
    {
    }

    ~ReadDoorLockEnablePrivacyModeButton() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000002B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster
            readAttributeEnablePrivacyModeButtonWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.EnablePrivacyModeButton response %@", [value description]);
                if (error != nil) {
                    LogNSError("DoorLock EnablePrivacyModeButton read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockEnablePrivacyModeButton : public WriteAttribute {
public:
    WriteDoorLockEnablePrivacyModeButton()
        : WriteAttribute("enable-privacy-mode-button")
    {
        AddArgument("attr-name", "enable-privacy-mode-button");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockEnablePrivacyModeButton() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x0000002B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeEnablePrivacyModeButtonWithValue:value
                                                         params:params
                                              completionHandler:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("DoorLock EnablePrivacyModeButton write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockEnablePrivacyModeButton : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockEnablePrivacyModeButton()
        : SubscribeAttribute("enable-privacy-mode-button")
    {
    }

    ~SubscribeAttributeDoorLockEnablePrivacyModeButton() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000002B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEnablePrivacyModeButtonWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.EnablePrivacyModeButton response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LocalProgrammingFeatures
 */
class ReadDoorLockLocalProgrammingFeatures : public ReadAttribute {
public:
    ReadDoorLockLocalProgrammingFeatures()
        : ReadAttribute("local-programming-features")
    {
    }

    ~ReadDoorLockLocalProgrammingFeatures() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000002C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster
            readAttributeLocalProgrammingFeaturesWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.LocalProgrammingFeatures response %@", [value description]);
                if (error != nil) {
                    LogNSError("DoorLock LocalProgrammingFeatures read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockLocalProgrammingFeatures : public WriteAttribute {
public:
    WriteDoorLockLocalProgrammingFeatures()
        : WriteAttribute("local-programming-features")
    {
        AddArgument("attr-name", "local-programming-features");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockLocalProgrammingFeatures() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x0000002C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeLocalProgrammingFeaturesWithValue:value
                                                          params:params
                                               completionHandler:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("DoorLock LocalProgrammingFeatures write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockLocalProgrammingFeatures : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockLocalProgrammingFeatures()
        : SubscribeAttribute("local-programming-features")
    {
    }

    ~SubscribeAttributeDoorLockLocalProgrammingFeatures() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000002C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLocalProgrammingFeaturesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.LocalProgrammingFeatures response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WrongCodeEntryLimit
 */
class ReadDoorLockWrongCodeEntryLimit : public ReadAttribute {
public:
    ReadDoorLockWrongCodeEntryLimit()
        : ReadAttribute("wrong-code-entry-limit")
    {
    }

    ~ReadDoorLockWrongCodeEntryLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeWrongCodeEntryLimitWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.WrongCodeEntryLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock WrongCodeEntryLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockWrongCodeEntryLimit : public WriteAttribute {
public:
    WriteDoorLockWrongCodeEntryLimit()
        : WriteAttribute("wrong-code-entry-limit")
    {
        AddArgument("attr-name", "wrong-code-entry-limit");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockWrongCodeEntryLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeWrongCodeEntryLimitWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("DoorLock WrongCodeEntryLimit write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockWrongCodeEntryLimit : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockWrongCodeEntryLimit()
        : SubscribeAttribute("wrong-code-entry-limit")
    {
    }

    ~SubscribeAttributeDoorLockWrongCodeEntryLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWrongCodeEntryLimitWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.WrongCodeEntryLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UserCodeTemporaryDisableTime
 */
class ReadDoorLockUserCodeTemporaryDisableTime : public ReadAttribute {
public:
    ReadDoorLockUserCodeTemporaryDisableTime()
        : ReadAttribute("user-code-temporary-disable-time")
    {
    }

    ~ReadDoorLockUserCodeTemporaryDisableTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeUserCodeTemporaryDisableTimeWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.UserCodeTemporaryDisableTime response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock UserCodeTemporaryDisableTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockUserCodeTemporaryDisableTime : public WriteAttribute {
public:
    WriteDoorLockUserCodeTemporaryDisableTime()
        : WriteAttribute("user-code-temporary-disable-time")
    {
        AddArgument("attr-name", "user-code-temporary-disable-time");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockUserCodeTemporaryDisableTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeUserCodeTemporaryDisableTimeWithValue:value
                                                              params:params
                                                   completionHandler:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError("DoorLock UserCodeTemporaryDisableTime write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockUserCodeTemporaryDisableTime : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockUserCodeTemporaryDisableTime()
        : SubscribeAttribute("user-code-temporary-disable-time")
    {
    }

    ~SubscribeAttributeDoorLockUserCodeTemporaryDisableTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUserCodeTemporaryDisableTimeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.UserCodeTemporaryDisableTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SendPINOverTheAir
 */
class ReadDoorLockSendPINOverTheAir : public ReadAttribute {
public:
    ReadDoorLockSendPINOverTheAir()
        : ReadAttribute("send-pinover-the-air")
    {
    }

    ~ReadDoorLockSendPINOverTheAir() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeSendPINOverTheAirWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.SendPINOverTheAir response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock SendPINOverTheAir read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockSendPINOverTheAir : public WriteAttribute {
public:
    WriteDoorLockSendPINOverTheAir()
        : WriteAttribute("send-pinover-the-air")
    {
        AddArgument("attr-name", "send-pinover-the-air");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockSendPINOverTheAir() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeSendPINOverTheAirWithValue:value
                                                   params:params
                                        completionHandler:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("DoorLock SendPINOverTheAir write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockSendPINOverTheAir : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockSendPINOverTheAir()
        : SubscribeAttribute("send-pinover-the-air")
    {
    }

    ~SubscribeAttributeDoorLockSendPINOverTheAir() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSendPINOverTheAirWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.SendPINOverTheAir response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RequirePINforRemoteOperation
 */
class ReadDoorLockRequirePINforRemoteOperation : public ReadAttribute {
public:
    ReadDoorLockRequirePINforRemoteOperation()
        : ReadAttribute("require-pinfor-remote-operation")
    {
    }

    ~ReadDoorLockRequirePINforRemoteOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000033) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeRequirePINforRemoteOperationWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.RequirePINforRemoteOperation response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock RequirePINforRemoteOperation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockRequirePINforRemoteOperation : public WriteAttribute {
public:
    WriteDoorLockRequirePINforRemoteOperation()
        : WriteAttribute("require-pinfor-remote-operation")
    {
        AddArgument("attr-name", "require-pinfor-remote-operation");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockRequirePINforRemoteOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeRequirePINforRemoteOperationWithValue:value
                                                              params:params
                                                   completionHandler:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError("DoorLock RequirePINforRemoteOperation write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockRequirePINforRemoteOperation : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockRequirePINforRemoteOperation()
        : SubscribeAttribute("require-pinfor-remote-operation")
    {
    }

    ~SubscribeAttributeDoorLockRequirePINforRemoteOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRequirePINforRemoteOperationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.RequirePINforRemoteOperation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ExpiringUserTimeout
 */
class ReadDoorLockExpiringUserTimeout : public ReadAttribute {
public:
    ReadDoorLockExpiringUserTimeout()
        : ReadAttribute("expiring-user-timeout")
    {
    }

    ~ReadDoorLockExpiringUserTimeout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000035) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeExpiringUserTimeoutWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.ExpiringUserTimeout response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock ExpiringUserTimeout read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockExpiringUserTimeout : public WriteAttribute {
public:
    WriteDoorLockExpiringUserTimeout()
        : WriteAttribute("expiring-user-timeout")
    {
        AddArgument("attr-name", "expiring-user-timeout");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockExpiringUserTimeout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeExpiringUserTimeoutWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("DoorLock ExpiringUserTimeout write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeDoorLockExpiringUserTimeout : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockExpiringUserTimeout()
        : SubscribeAttribute("expiring-user-timeout")
    {
    }

    ~SubscribeAttributeDoorLockExpiringUserTimeout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeExpiringUserTimeoutWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.ExpiringUserTimeout response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadDoorLockGeneratedCommandList : public ReadAttribute {
public:
    ReadDoorLockGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadDoorLockGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeDoorLockGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadDoorLockAcceptedCommandList : public ReadAttribute {
public:
    ReadDoorLockAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadDoorLockAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeDoorLockAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadDoorLockAttributeList : public ReadAttribute {
public:
    ReadDoorLockAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadDoorLockAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeDoorLockAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadDoorLockFeatureMap : public ReadAttribute {
public:
    ReadDoorLockFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadDoorLockFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeDoorLockFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadDoorLockClusterRevision : public ReadAttribute {
public:
    ReadDoorLockClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadDoorLockClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeDoorLockClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster WindowCovering                                              | 0x0102 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * UpOrOpen                                                          |   0x00 |
| * DownOrClose                                                       |   0x01 |
| * StopMotion                                                        |   0x02 |
| * GoToLiftValue                                                     |   0x04 |
| * GoToLiftPercentage                                                |   0x05 |
| * GoToTiltValue                                                     |   0x07 |
| * GoToTiltPercentage                                                |   0x08 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Type                                                              | 0x0000 |
| * PhysicalClosedLimitLift                                           | 0x0001 |
| * PhysicalClosedLimitTilt                                           | 0x0002 |
| * CurrentPositionLift                                               | 0x0003 |
| * CurrentPositionTilt                                               | 0x0004 |
| * NumberOfActuationsLift                                            | 0x0005 |
| * NumberOfActuationsTilt                                            | 0x0006 |
| * ConfigStatus                                                      | 0x0007 |
| * CurrentPositionLiftPercentage                                     | 0x0008 |
| * CurrentPositionTiltPercentage                                     | 0x0009 |
| * OperationalStatus                                                 | 0x000A |
| * TargetPositionLiftPercent100ths                                   | 0x000B |
| * TargetPositionTiltPercent100ths                                   | 0x000C |
| * EndProductType                                                    | 0x000D |
| * CurrentPositionLiftPercent100ths                                  | 0x000E |
| * CurrentPositionTiltPercent100ths                                  | 0x000F |
| * InstalledOpenLimitLift                                            | 0x0010 |
| * InstalledClosedLimitLift                                          | 0x0011 |
| * InstalledOpenLimitTilt                                            | 0x0012 |
| * InstalledClosedLimitTilt                                          | 0x0013 |
| * Mode                                                              | 0x0017 |
| * SafetyStatus                                                      | 0x001A |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command UpOrOpen
 */
class WindowCoveringUpOrOpen : public ClusterCommand {
public:
    WindowCoveringUpOrOpen()
        : ClusterCommand("up-or-open")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint: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
                      completionHandler:^(NSError * _Nullable error) {
                          responsesNeeded--;
                          if (error != nil) {
                              mError = error;
                              LogNSError("Error", error);
                          }
                          if (responsesNeeded == 0) {
                              SetCommandExitStatus(mError);
                          }
                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command DownOrClose
 */
class WindowCoveringDownOrClose : public ClusterCommand {
public:
    WindowCoveringDownOrClose()
        : ClusterCommand("down-or-close")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint: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
                         completionHandler:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command StopMotion
 */
class WindowCoveringStopMotion : public ClusterCommand {
public:
    WindowCoveringStopMotion()
        : ClusterCommand("stop-motion")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint: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
                        completionHandler:^(NSError * _Nullable error) {
                            responsesNeeded--;
                            if (error != nil) {
                                mError = error;
                                LogNSError("Error", error);
                            }
                            if (responsesNeeded == 0) {
                                SetCommandExitStatus(mError);
                            }
                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command GoToLiftValue
 */
class WindowCoveringGoToLiftValue : public ClusterCommand {
public:
    WindowCoveringGoToLiftValue()
        : ClusterCommand("go-to-lift-value")
    {
        AddArgument("LiftValue", 0, UINT16_MAX, &mRequest.liftValue);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint: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
                           completionHandler:^(NSError * _Nullable error) {
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::WindowCovering::Commands::GoToLiftValue::Type mRequest;
};

/*
 * Command GoToLiftPercentage
 */
class WindowCoveringGoToLiftPercentage : public ClusterCommand {
public:
    WindowCoveringGoToLiftPercentage()
        : ClusterCommand("go-to-lift-percentage")
    {
        AddArgument("LiftPercent100thsValue", 0, UINT16_MAX, &mRequest.liftPercent100thsValue);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint: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
                                completionHandler:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::WindowCovering::Commands::GoToLiftPercentage::Type mRequest;
};

/*
 * Command GoToTiltValue
 */
class WindowCoveringGoToTiltValue : public ClusterCommand {
public:
    WindowCoveringGoToTiltValue()
        : ClusterCommand("go-to-tilt-value")
    {
        AddArgument("TiltValue", 0, UINT16_MAX, &mRequest.tiltValue);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint: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
                           completionHandler:^(NSError * _Nullable error) {
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::WindowCovering::Commands::GoToTiltValue::Type mRequest;
};

/*
 * Command GoToTiltPercentage
 */
class WindowCoveringGoToTiltPercentage : public ClusterCommand {
public:
    WindowCoveringGoToTiltPercentage()
        : ClusterCommand("go-to-tilt-percentage")
    {
        AddArgument("TiltPercent100thsValue", 0, UINT16_MAX, &mRequest.tiltPercent100thsValue);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint: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
                                completionHandler:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::WindowCovering::Commands::GoToTiltPercentage::Type mRequest;
};

/*
 * Attribute Type
 */
class ReadWindowCoveringType : public ReadAttribute {
public:
    ReadWindowCoveringType()
        : ReadAttribute("type")
    {
    }

    ~ReadWindowCoveringType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.Type response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering Type read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringType : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringType()
        : SubscribeAttribute("type")
    {
    }

    ~SubscribeAttributeWindowCoveringType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.Type response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalClosedLimitLift
 */
class ReadWindowCoveringPhysicalClosedLimitLift : public ReadAttribute {
public:
    ReadWindowCoveringPhysicalClosedLimitLift()
        : ReadAttribute("physical-closed-limit-lift")
    {
    }

    ~ReadWindowCoveringPhysicalClosedLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster
            readAttributePhysicalClosedLimitLiftWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.PhysicalClosedLimitLift response %@", [value description]);
                if (error != nil) {
                    LogNSError("WindowCovering PhysicalClosedLimitLift read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringPhysicalClosedLimitLift : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringPhysicalClosedLimitLift()
        : SubscribeAttribute("physical-closed-limit-lift")
    {
    }

    ~SubscribeAttributeWindowCoveringPhysicalClosedLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePhysicalClosedLimitLiftWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.PhysicalClosedLimitLift response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalClosedLimitTilt
 */
class ReadWindowCoveringPhysicalClosedLimitTilt : public ReadAttribute {
public:
    ReadWindowCoveringPhysicalClosedLimitTilt()
        : ReadAttribute("physical-closed-limit-tilt")
    {
    }

    ~ReadWindowCoveringPhysicalClosedLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster
            readAttributePhysicalClosedLimitTiltWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.PhysicalClosedLimitTilt response %@", [value description]);
                if (error != nil) {
                    LogNSError("WindowCovering PhysicalClosedLimitTilt read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringPhysicalClosedLimitTilt : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringPhysicalClosedLimitTilt()
        : SubscribeAttribute("physical-closed-limit-tilt")
    {
    }

    ~SubscribeAttributeWindowCoveringPhysicalClosedLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePhysicalClosedLimitTiltWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.PhysicalClosedLimitTilt response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionLift
 */
class ReadWindowCoveringCurrentPositionLift : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionLift()
        : ReadAttribute("current-position-lift")
    {
    }

    ~ReadWindowCoveringCurrentPositionLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionLiftWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.CurrentPositionLift response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering CurrentPositionLift read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionLift : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionLift()
        : SubscribeAttribute("current-position-lift")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentPositionLiftWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionLift response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionTilt
 */
class ReadWindowCoveringCurrentPositionTilt : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionTilt()
        : ReadAttribute("current-position-tilt")
    {
    }

    ~ReadWindowCoveringCurrentPositionTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionTiltWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.CurrentPositionTilt response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering CurrentPositionTilt read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionTilt : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionTilt()
        : SubscribeAttribute("current-position-tilt")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentPositionTiltWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionTilt response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfActuationsLift
 */
class ReadWindowCoveringNumberOfActuationsLift : public ReadAttribute {
public:
    ReadWindowCoveringNumberOfActuationsLift()
        : ReadAttribute("number-of-actuations-lift")
    {
    }

    ~ReadWindowCoveringNumberOfActuationsLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeNumberOfActuationsLiftWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.NumberOfActuationsLift response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering NumberOfActuationsLift read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringNumberOfActuationsLift : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringNumberOfActuationsLift()
        : SubscribeAttribute("number-of-actuations-lift")
    {
    }

    ~SubscribeAttributeWindowCoveringNumberOfActuationsLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfActuationsLiftWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.NumberOfActuationsLift response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfActuationsTilt
 */
class ReadWindowCoveringNumberOfActuationsTilt : public ReadAttribute {
public:
    ReadWindowCoveringNumberOfActuationsTilt()
        : ReadAttribute("number-of-actuations-tilt")
    {
    }

    ~ReadWindowCoveringNumberOfActuationsTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeNumberOfActuationsTiltWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.NumberOfActuationsTilt response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering NumberOfActuationsTilt read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringNumberOfActuationsTilt : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringNumberOfActuationsTilt()
        : SubscribeAttribute("number-of-actuations-tilt")
    {
    }

    ~SubscribeAttributeWindowCoveringNumberOfActuationsTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfActuationsTiltWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.NumberOfActuationsTilt response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ConfigStatus
 */
class ReadWindowCoveringConfigStatus : public ReadAttribute {
public:
    ReadWindowCoveringConfigStatus()
        : ReadAttribute("config-status")
    {
    }

    ~ReadWindowCoveringConfigStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeConfigStatusWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.ConfigStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering ConfigStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringConfigStatus : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringConfigStatus()
        : SubscribeAttribute("config-status")
    {
    }

    ~SubscribeAttributeWindowCoveringConfigStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeConfigStatusWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.ConfigStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionLiftPercentage
 */
class ReadWindowCoveringCurrentPositionLiftPercentage : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionLiftPercentage()
        : ReadAttribute("current-position-lift-percentage")
    {
    }

    ~ReadWindowCoveringCurrentPositionLiftPercentage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionLiftPercentageWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.CurrentPositionLiftPercentage response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering CurrentPositionLiftPercentage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionLiftPercentage : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionLiftPercentage()
        : SubscribeAttribute("current-position-lift-percentage")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionLiftPercentage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentPositionLiftPercentageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionLiftPercentage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionTiltPercentage
 */
class ReadWindowCoveringCurrentPositionTiltPercentage : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionTiltPercentage()
        : ReadAttribute("current-position-tilt-percentage")
    {
    }

    ~ReadWindowCoveringCurrentPositionTiltPercentage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionTiltPercentageWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.CurrentPositionTiltPercentage response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering CurrentPositionTiltPercentage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionTiltPercentage : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionTiltPercentage()
        : SubscribeAttribute("current-position-tilt-percentage")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionTiltPercentage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentPositionTiltPercentageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionTiltPercentage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OperationalStatus
 */
class ReadWindowCoveringOperationalStatus : public ReadAttribute {
public:
    ReadWindowCoveringOperationalStatus()
        : ReadAttribute("operational-status")
    {
    }

    ~ReadWindowCoveringOperationalStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeOperationalStatusWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.OperationalStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering OperationalStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringOperationalStatus : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringOperationalStatus()
        : SubscribeAttribute("operational-status")
    {
    }

    ~SubscribeAttributeWindowCoveringOperationalStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOperationalStatusWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.OperationalStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TargetPositionLiftPercent100ths
 */
class ReadWindowCoveringTargetPositionLiftPercent100ths : public ReadAttribute {
public:
    ReadWindowCoveringTargetPositionLiftPercent100ths()
        : ReadAttribute("target-position-lift-percent100ths")
    {
    }

    ~ReadWindowCoveringTargetPositionLiftPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeTargetPositionLiftPercent100thsWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.TargetPositionLiftPercent100ths response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering TargetPositionLiftPercent100ths read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringTargetPositionLiftPercent100ths : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringTargetPositionLiftPercent100ths()
        : SubscribeAttribute("target-position-lift-percent100ths")
    {
    }

    ~SubscribeAttributeWindowCoveringTargetPositionLiftPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTargetPositionLiftPercent100thsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.TargetPositionLiftPercent100ths response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TargetPositionTiltPercent100ths
 */
class ReadWindowCoveringTargetPositionTiltPercent100ths : public ReadAttribute {
public:
    ReadWindowCoveringTargetPositionTiltPercent100ths()
        : ReadAttribute("target-position-tilt-percent100ths")
    {
    }

    ~ReadWindowCoveringTargetPositionTiltPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeTargetPositionTiltPercent100thsWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.TargetPositionTiltPercent100ths response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering TargetPositionTiltPercent100ths read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringTargetPositionTiltPercent100ths : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringTargetPositionTiltPercent100ths()
        : SubscribeAttribute("target-position-tilt-percent100ths")
    {
    }

    ~SubscribeAttributeWindowCoveringTargetPositionTiltPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTargetPositionTiltPercent100thsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.TargetPositionTiltPercent100ths response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EndProductType
 */
class ReadWindowCoveringEndProductType : public ReadAttribute {
public:
    ReadWindowCoveringEndProductType()
        : ReadAttribute("end-product-type")
    {
    }

    ~ReadWindowCoveringEndProductType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeEndProductTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.EndProductType response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering EndProductType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringEndProductType : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringEndProductType()
        : SubscribeAttribute("end-product-type")
    {
    }

    ~SubscribeAttributeWindowCoveringEndProductType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEndProductTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.EndProductType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionLiftPercent100ths
 */
class ReadWindowCoveringCurrentPositionLiftPercent100ths : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionLiftPercent100ths()
        : ReadAttribute("current-position-lift-percent100ths")
    {
    }

    ~ReadWindowCoveringCurrentPositionLiftPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionLiftPercent100thsWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.CurrentPositionLiftPercent100ths response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering CurrentPositionLiftPercent100ths read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionLiftPercent100ths : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionLiftPercent100ths()
        : SubscribeAttribute("current-position-lift-percent100ths")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionLiftPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentPositionLiftPercent100thsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionLiftPercent100ths response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionTiltPercent100ths
 */
class ReadWindowCoveringCurrentPositionTiltPercent100ths : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionTiltPercent100ths()
        : ReadAttribute("current-position-tilt-percent100ths")
    {
    }

    ~ReadWindowCoveringCurrentPositionTiltPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionTiltPercent100thsWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.CurrentPositionTiltPercent100ths response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering CurrentPositionTiltPercent100ths read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionTiltPercent100ths : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionTiltPercent100ths()
        : SubscribeAttribute("current-position-tilt-percent100ths")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionTiltPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentPositionTiltPercent100thsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionTiltPercent100ths response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstalledOpenLimitLift
 */
class ReadWindowCoveringInstalledOpenLimitLift : public ReadAttribute {
public:
    ReadWindowCoveringInstalledOpenLimitLift()
        : ReadAttribute("installed-open-limit-lift")
    {
    }

    ~ReadWindowCoveringInstalledOpenLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeInstalledOpenLimitLiftWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.InstalledOpenLimitLift response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering InstalledOpenLimitLift read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringInstalledOpenLimitLift : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringInstalledOpenLimitLift()
        : SubscribeAttribute("installed-open-limit-lift")
    {
    }

    ~SubscribeAttributeWindowCoveringInstalledOpenLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInstalledOpenLimitLiftWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.InstalledOpenLimitLift response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstalledClosedLimitLift
 */
class ReadWindowCoveringInstalledClosedLimitLift : public ReadAttribute {
public:
    ReadWindowCoveringInstalledClosedLimitLift()
        : ReadAttribute("installed-closed-limit-lift")
    {
    }

    ~ReadWindowCoveringInstalledClosedLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster
            readAttributeInstalledClosedLimitLiftWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.InstalledClosedLimitLift response %@", [value description]);
                if (error != nil) {
                    LogNSError("WindowCovering InstalledClosedLimitLift read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringInstalledClosedLimitLift : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringInstalledClosedLimitLift()
        : SubscribeAttribute("installed-closed-limit-lift")
    {
    }

    ~SubscribeAttributeWindowCoveringInstalledClosedLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInstalledClosedLimitLiftWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.InstalledClosedLimitLift response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstalledOpenLimitTilt
 */
class ReadWindowCoveringInstalledOpenLimitTilt : public ReadAttribute {
public:
    ReadWindowCoveringInstalledOpenLimitTilt()
        : ReadAttribute("installed-open-limit-tilt")
    {
    }

    ~ReadWindowCoveringInstalledOpenLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeInstalledOpenLimitTiltWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.InstalledOpenLimitTilt response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering InstalledOpenLimitTilt read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringInstalledOpenLimitTilt : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringInstalledOpenLimitTilt()
        : SubscribeAttribute("installed-open-limit-tilt")
    {
    }

    ~SubscribeAttributeWindowCoveringInstalledOpenLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInstalledOpenLimitTiltWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.InstalledOpenLimitTilt response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstalledClosedLimitTilt
 */
class ReadWindowCoveringInstalledClosedLimitTilt : public ReadAttribute {
public:
    ReadWindowCoveringInstalledClosedLimitTilt()
        : ReadAttribute("installed-closed-limit-tilt")
    {
    }

    ~ReadWindowCoveringInstalledClosedLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster
            readAttributeInstalledClosedLimitTiltWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.InstalledClosedLimitTilt response %@", [value description]);
                if (error != nil) {
                    LogNSError("WindowCovering InstalledClosedLimitTilt read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringInstalledClosedLimitTilt : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringInstalledClosedLimitTilt()
        : SubscribeAttribute("installed-closed-limit-tilt")
    {
    }

    ~SubscribeAttributeWindowCoveringInstalledClosedLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInstalledClosedLimitTiltWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.InstalledClosedLimitTilt response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Mode
 */
class ReadWindowCoveringMode : public ReadAttribute {
public:
    ReadWindowCoveringMode()
        : ReadAttribute("mode")
    {
    }

    ~ReadWindowCoveringMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.Mode response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering Mode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteWindowCoveringMode : public WriteAttribute {
public:
    WriteWindowCoveringMode()
        : WriteAttribute("mode")
    {
        AddArgument("attr-name", "mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteWindowCoveringMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) WriteAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeModeWithValue:value
                                      params:params
                           completionHandler:^(NSError * _Nullable error) {
                               if (error != nil) {
                                   LogNSError("WindowCovering Mode write Error", error);
                               }
                               SetCommandExitStatus(error);
                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeWindowCoveringMode : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringMode()
        : SubscribeAttribute("mode")
    {
    }

    ~SubscribeAttributeWindowCoveringMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.Mode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SafetyStatus
 */
class ReadWindowCoveringSafetyStatus : public ReadAttribute {
public:
    ReadWindowCoveringSafetyStatus()
        : ReadAttribute("safety-status")
    {
    }

    ~ReadWindowCoveringSafetyStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeSafetyStatusWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.SafetyStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering SafetyStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringSafetyStatus : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringSafetyStatus()
        : SubscribeAttribute("safety-status")
    {
    }

    ~SubscribeAttributeWindowCoveringSafetyStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSafetyStatusWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.SafetyStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadWindowCoveringGeneratedCommandList : public ReadAttribute {
public:
    ReadWindowCoveringGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadWindowCoveringGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeWindowCoveringGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadWindowCoveringAcceptedCommandList : public ReadAttribute {
public:
    ReadWindowCoveringAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadWindowCoveringAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeWindowCoveringAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadWindowCoveringAttributeList : public ReadAttribute {
public:
    ReadWindowCoveringAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadWindowCoveringAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeWindowCoveringAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadWindowCoveringFeatureMap : public ReadAttribute {
public:
    ReadWindowCoveringFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadWindowCoveringFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeWindowCoveringFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadWindowCoveringClusterRevision : public ReadAttribute {
public:
    ReadWindowCoveringClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadWindowCoveringClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeWindowCoveringClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster BarrierControl                                              | 0x0103 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * BarrierControlGoToPercent                                         |   0x00 |
| * BarrierControlStop                                                |   0x01 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * BarrierMovingState                                                | 0x0001 |
| * BarrierSafetyStatus                                               | 0x0002 |
| * BarrierCapabilities                                               | 0x0003 |
| * BarrierOpenEvents                                                 | 0x0004 |
| * BarrierCloseEvents                                                | 0x0005 |
| * BarrierCommandOpenEvents                                          | 0x0006 |
| * BarrierCommandCloseEvents                                         | 0x0007 |
| * BarrierOpenPeriod                                                 | 0x0008 |
| * BarrierClosePeriod                                                | 0x0009 |
| * BarrierPosition                                                   | 0x000A |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command BarrierControlGoToPercent
 */
class BarrierControlBarrierControlGoToPercent : public ClusterCommand {
public:
    BarrierControlBarrierControlGoToPercent()
        : ClusterCommand("barrier-control-go-to-percent")
    {
        AddArgument("PercentOpen", 0, UINT8_MAX, &mRequest.percentOpen);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint: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
                                       completionHandler:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::BarrierControl::Commands::BarrierControlGoToPercent::Type mRequest;
};

/*
 * Command BarrierControlStop
 */
class BarrierControlBarrierControlStop : public ClusterCommand {
public:
    BarrierControlBarrierControlStop()
        : ClusterCommand("barrier-control-stop")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint: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
                                completionHandler:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute BarrierMovingState
 */
class ReadBarrierControlBarrierMovingState : public ReadAttribute {
public:
    ReadBarrierControlBarrierMovingState()
        : ReadAttribute("barrier-moving-state")
    {
    }

    ~ReadBarrierControlBarrierMovingState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierMovingStateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierMovingState response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierMovingState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlBarrierMovingState : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierMovingState()
        : SubscribeAttribute("barrier-moving-state")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierMovingState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBarrierMovingStateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierMovingState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierSafetyStatus
 */
class ReadBarrierControlBarrierSafetyStatus : public ReadAttribute {
public:
    ReadBarrierControlBarrierSafetyStatus()
        : ReadAttribute("barrier-safety-status")
    {
    }

    ~ReadBarrierControlBarrierSafetyStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierSafetyStatusWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierSafetyStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierSafetyStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlBarrierSafetyStatus : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierSafetyStatus()
        : SubscribeAttribute("barrier-safety-status")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierSafetyStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBarrierSafetyStatusWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierSafetyStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierCapabilities
 */
class ReadBarrierControlBarrierCapabilities : public ReadAttribute {
public:
    ReadBarrierControlBarrierCapabilities()
        : ReadAttribute("barrier-capabilities")
    {
    }

    ~ReadBarrierControlBarrierCapabilities() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierCapabilitiesWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierCapabilities response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierCapabilities read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlBarrierCapabilities : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierCapabilities()
        : SubscribeAttribute("barrier-capabilities")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierCapabilities() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBarrierCapabilitiesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierCapabilities response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierOpenEvents
 */
class ReadBarrierControlBarrierOpenEvents : public ReadAttribute {
public:
    ReadBarrierControlBarrierOpenEvents()
        : ReadAttribute("barrier-open-events")
    {
    }

    ~ReadBarrierControlBarrierOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierOpenEventsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierOpenEvents response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierOpenEvents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierOpenEvents : public WriteAttribute {
public:
    WriteBarrierControlBarrierOpenEvents()
        : WriteAttribute("barrier-open-events")
    {
        AddArgument("attr-name", "barrier-open-events");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBarrierOpenEventsWithValue:value
                                                   params:params
                                        completionHandler:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("BarrierControl BarrierOpenEvents write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierOpenEvents : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierOpenEvents()
        : SubscribeAttribute("barrier-open-events")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBarrierOpenEventsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierOpenEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierCloseEvents
 */
class ReadBarrierControlBarrierCloseEvents : public ReadAttribute {
public:
    ReadBarrierControlBarrierCloseEvents()
        : ReadAttribute("barrier-close-events")
    {
    }

    ~ReadBarrierControlBarrierCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierCloseEventsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierCloseEvents response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierCloseEvents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierCloseEvents : public WriteAttribute {
public:
    WriteBarrierControlBarrierCloseEvents()
        : WriteAttribute("barrier-close-events")
    {
        AddArgument("attr-name", "barrier-close-events");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBarrierCloseEventsWithValue:value
                                                    params:params
                                         completionHandler:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("BarrierControl BarrierCloseEvents write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierCloseEvents : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierCloseEvents()
        : SubscribeAttribute("barrier-close-events")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBarrierCloseEventsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierCloseEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierCommandOpenEvents
 */
class ReadBarrierControlBarrierCommandOpenEvents : public ReadAttribute {
public:
    ReadBarrierControlBarrierCommandOpenEvents()
        : ReadAttribute("barrier-command-open-events")
    {
    }

    ~ReadBarrierControlBarrierCommandOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster
            readAttributeBarrierCommandOpenEventsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierCommandOpenEvents response %@", [value description]);
                if (error != nil) {
                    LogNSError("BarrierControl BarrierCommandOpenEvents read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierCommandOpenEvents : public WriteAttribute {
public:
    WriteBarrierControlBarrierCommandOpenEvents()
        : WriteAttribute("barrier-command-open-events")
    {
        AddArgument("attr-name", "barrier-command-open-events");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierCommandOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBarrierCommandOpenEventsWithValue:value
                                                          params:params
                                               completionHandler:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("BarrierControl BarrierCommandOpenEvents write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierCommandOpenEvents : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierCommandOpenEvents()
        : SubscribeAttribute("barrier-command-open-events")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierCommandOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBarrierCommandOpenEventsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierCommandOpenEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierCommandCloseEvents
 */
class ReadBarrierControlBarrierCommandCloseEvents : public ReadAttribute {
public:
    ReadBarrierControlBarrierCommandCloseEvents()
        : ReadAttribute("barrier-command-close-events")
    {
    }

    ~ReadBarrierControlBarrierCommandCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster
            readAttributeBarrierCommandCloseEventsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierCommandCloseEvents response %@", [value description]);
                if (error != nil) {
                    LogNSError("BarrierControl BarrierCommandCloseEvents read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierCommandCloseEvents : public WriteAttribute {
public:
    WriteBarrierControlBarrierCommandCloseEvents()
        : WriteAttribute("barrier-command-close-events")
    {
        AddArgument("attr-name", "barrier-command-close-events");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierCommandCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBarrierCommandCloseEventsWithValue:value
                                                           params:params
                                                completionHandler:^(NSError * _Nullable error) {
                                                    if (error != nil) {
                                                        LogNSError("BarrierControl BarrierCommandCloseEvents write Error", error);
                                                    }
                                                    SetCommandExitStatus(error);
                                                }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierCommandCloseEvents : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierCommandCloseEvents()
        : SubscribeAttribute("barrier-command-close-events")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierCommandCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBarrierCommandCloseEventsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierCommandCloseEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierOpenPeriod
 */
class ReadBarrierControlBarrierOpenPeriod : public ReadAttribute {
public:
    ReadBarrierControlBarrierOpenPeriod()
        : ReadAttribute("barrier-open-period")
    {
    }

    ~ReadBarrierControlBarrierOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierOpenPeriodWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierOpenPeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierOpenPeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierOpenPeriod : public WriteAttribute {
public:
    WriteBarrierControlBarrierOpenPeriod()
        : WriteAttribute("barrier-open-period")
    {
        AddArgument("attr-name", "barrier-open-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBarrierOpenPeriodWithValue:value
                                                   params:params
                                        completionHandler:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("BarrierControl BarrierOpenPeriod write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierOpenPeriod : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierOpenPeriod()
        : SubscribeAttribute("barrier-open-period")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBarrierOpenPeriodWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierOpenPeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierClosePeriod
 */
class ReadBarrierControlBarrierClosePeriod : public ReadAttribute {
public:
    ReadBarrierControlBarrierClosePeriod()
        : ReadAttribute("barrier-close-period")
    {
    }

    ~ReadBarrierControlBarrierClosePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierClosePeriodWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierClosePeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierClosePeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierClosePeriod : public WriteAttribute {
public:
    WriteBarrierControlBarrierClosePeriod()
        : WriteAttribute("barrier-close-period")
    {
        AddArgument("attr-name", "barrier-close-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierClosePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBarrierClosePeriodWithValue:value
                                                    params:params
                                         completionHandler:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("BarrierControl BarrierClosePeriod write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierClosePeriod : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierClosePeriod()
        : SubscribeAttribute("barrier-close-period")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierClosePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBarrierClosePeriodWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierClosePeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierPosition
 */
class ReadBarrierControlBarrierPosition : public ReadAttribute {
public:
    ReadBarrierControlBarrierPosition()
        : ReadAttribute("barrier-position")
    {
    }

    ~ReadBarrierControlBarrierPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierPositionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierPosition response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierPosition read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlBarrierPosition : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierPosition()
        : SubscribeAttribute("barrier-position")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBarrierPositionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierPosition response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBarrierControlGeneratedCommandList : public ReadAttribute {
public:
    ReadBarrierControlGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBarrierControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBarrierControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBarrierControlAcceptedCommandList : public ReadAttribute {
public:
    ReadBarrierControlAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBarrierControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBarrierControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBarrierControlAttributeList : public ReadAttribute {
public:
    ReadBarrierControlAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBarrierControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBarrierControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBarrierControlFeatureMap : public ReadAttribute {
public:
    ReadBarrierControlFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBarrierControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBarrierControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBarrierControlClusterRevision : public ReadAttribute {
public:
    ReadBarrierControlClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBarrierControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBarrierControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                             endpoint:endpointId
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster PumpConfigurationAndControl                                 | 0x0200 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MaxPressure                                                       | 0x0000 |
| * MaxSpeed                                                          | 0x0001 |
| * MaxFlow                                                           | 0x0002 |
| * MinConstPressure                                                  | 0x0003 |
| * MaxConstPressure                                                  | 0x0004 |
| * MinCompPressure                                                   | 0x0005 |
| * MaxCompPressure                                                   | 0x0006 |
| * MinConstSpeed                                                     | 0x0007 |
| * MaxConstSpeed                                                     | 0x0008 |
| * MinConstFlow                                                      | 0x0009 |
| * MaxConstFlow                                                      | 0x000A |
| * MinConstTemp                                                      | 0x000B |
| * MaxConstTemp                                                      | 0x000C |
| * PumpStatus                                                        | 0x0010 |
| * EffectiveOperationMode                                            | 0x0011 |
| * EffectiveControlMode                                              | 0x0012 |
| * Capacity                                                          | 0x0013 |
| * Speed                                                             | 0x0014 |
| * LifetimeRunningHours                                              | 0x0015 |
| * Power                                                             | 0x0016 |
| * LifetimeEnergyConsumed                                            | 0x0017 |
| * OperationMode                                                     | 0x0020 |
| * ControlMode                                                       | 0x0021 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * SupplyVoltageLow                                                  | 0x0000 |
| * SupplyVoltageHigh                                                 | 0x0001 |
| * PowerMissingPhase                                                 | 0x0002 |
| * SystemPressureLow                                                 | 0x0003 |
| * SystemPressureHigh                                                | 0x0004 |
| * DryRunning                                                        | 0x0005 |
| * MotorTemperatureHigh                                              | 0x0006 |
| * PumpMotorFatalFailure                                             | 0x0007 |
| * ElectronicTemperatureHigh                                         | 0x0008 |
| * PumpBlocked                                                       | 0x0009 |
| * SensorFailure                                                     | 0x000A |
| * ElectronicNonFatalFailure                                         | 0x000B |
| * ElectronicFatalFailure                                            | 0x000C |
| * GeneralFault                                                      | 0x000D |
| * Leakage                                                           | 0x000E |
| * AirDetection                                                      | 0x000F |
| * TurbineOperation                                                  | 0x0010 |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MaxPressure
 */
class ReadPumpConfigurationAndControlMaxPressure : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxPressure()
        : ReadAttribute("max-pressure")
    {
    }

    ~ReadPumpConfigurationAndControlMaxPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxPressureWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxPressure response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxPressure read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxPressure : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxPressure()
        : SubscribeAttribute("max-pressure")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxPressureWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxPressure response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxSpeed
 */
class ReadPumpConfigurationAndControlMaxSpeed : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxSpeed()
        : ReadAttribute("max-speed")
    {
    }

    ~ReadPumpConfigurationAndControlMaxSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxSpeedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxSpeed response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxSpeed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxSpeed : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxSpeed()
        : SubscribeAttribute("max-speed")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxSpeedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxSpeed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxFlow
 */
class ReadPumpConfigurationAndControlMaxFlow : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxFlow()
        : ReadAttribute("max-flow")
    {
    }

    ~ReadPumpConfigurationAndControlMaxFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxFlowWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxFlow response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxFlow read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxFlow : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxFlow()
        : SubscribeAttribute("max-flow")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxFlowWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxFlow response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinConstPressure
 */
class ReadPumpConfigurationAndControlMinConstPressure : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMinConstPressure()
        : ReadAttribute("min-const-pressure")
    {
    }

    ~ReadPumpConfigurationAndControlMinConstPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMinConstPressureWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MinConstPressure response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MinConstPressure read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMinConstPressure : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMinConstPressure()
        : SubscribeAttribute("min-const-pressure")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMinConstPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinConstPressureWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MinConstPressure response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxConstPressure
 */
class ReadPumpConfigurationAndControlMaxConstPressure : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxConstPressure()
        : ReadAttribute("max-const-pressure")
    {
    }

    ~ReadPumpConfigurationAndControlMaxConstPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxConstPressureWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxConstPressure response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxConstPressure read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxConstPressure : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxConstPressure()
        : SubscribeAttribute("max-const-pressure")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxConstPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxConstPressureWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxConstPressure response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinCompPressure
 */
class ReadPumpConfigurationAndControlMinCompPressure : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMinCompPressure()
        : ReadAttribute("min-comp-pressure")
    {
    }

    ~ReadPumpConfigurationAndControlMinCompPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMinCompPressureWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MinCompPressure response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MinCompPressure read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMinCompPressure : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMinCompPressure()
        : SubscribeAttribute("min-comp-pressure")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMinCompPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinCompPressureWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MinCompPressure response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxCompPressure
 */
class ReadPumpConfigurationAndControlMaxCompPressure : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxCompPressure()
        : ReadAttribute("max-comp-pressure")
    {
    }

    ~ReadPumpConfigurationAndControlMaxCompPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxCompPressureWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxCompPressure response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxCompPressure read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxCompPressure : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxCompPressure()
        : SubscribeAttribute("max-comp-pressure")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxCompPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxCompPressureWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxCompPressure response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinConstSpeed
 */
class ReadPumpConfigurationAndControlMinConstSpeed : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMinConstSpeed()
        : ReadAttribute("min-const-speed")
    {
    }

    ~ReadPumpConfigurationAndControlMinConstSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMinConstSpeedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MinConstSpeed response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MinConstSpeed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMinConstSpeed : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMinConstSpeed()
        : SubscribeAttribute("min-const-speed")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMinConstSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinConstSpeedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MinConstSpeed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxConstSpeed
 */
class ReadPumpConfigurationAndControlMaxConstSpeed : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxConstSpeed()
        : ReadAttribute("max-const-speed")
    {
    }

    ~ReadPumpConfigurationAndControlMaxConstSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxConstSpeedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxConstSpeed response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxConstSpeed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxConstSpeed : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxConstSpeed()
        : SubscribeAttribute("max-const-speed")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxConstSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxConstSpeedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxConstSpeed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinConstFlow
 */
class ReadPumpConfigurationAndControlMinConstFlow : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMinConstFlow()
        : ReadAttribute("min-const-flow")
    {
    }

    ~ReadPumpConfigurationAndControlMinConstFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMinConstFlowWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MinConstFlow response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MinConstFlow read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMinConstFlow : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMinConstFlow()
        : SubscribeAttribute("min-const-flow")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMinConstFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinConstFlowWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MinConstFlow response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxConstFlow
 */
class ReadPumpConfigurationAndControlMaxConstFlow : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxConstFlow()
        : ReadAttribute("max-const-flow")
    {
    }

    ~ReadPumpConfigurationAndControlMaxConstFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxConstFlowWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxConstFlow response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxConstFlow read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxConstFlow : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxConstFlow()
        : SubscribeAttribute("max-const-flow")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxConstFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxConstFlowWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxConstFlow response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinConstTemp
 */
class ReadPumpConfigurationAndControlMinConstTemp : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMinConstTemp()
        : ReadAttribute("min-const-temp")
    {
    }

    ~ReadPumpConfigurationAndControlMinConstTemp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMinConstTempWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MinConstTemp response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MinConstTemp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMinConstTemp : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMinConstTemp()
        : SubscribeAttribute("min-const-temp")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMinConstTemp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinConstTempWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MinConstTemp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxConstTemp
 */
class ReadPumpConfigurationAndControlMaxConstTemp : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxConstTemp()
        : ReadAttribute("max-const-temp")
    {
    }

    ~ReadPumpConfigurationAndControlMaxConstTemp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxConstTempWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxConstTemp response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxConstTemp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxConstTemp : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxConstTemp()
        : SubscribeAttribute("max-const-temp")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxConstTemp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxConstTempWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxConstTemp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PumpStatus
 */
class ReadPumpConfigurationAndControlPumpStatus : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlPumpStatus()
        : ReadAttribute("pump-status")
    {
    }

    ~ReadPumpConfigurationAndControlPumpStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePumpStatusWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.PumpStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl PumpStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlPumpStatus : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlPumpStatus()
        : SubscribeAttribute("pump-status")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlPumpStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePumpStatusWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.PumpStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EffectiveOperationMode
 */
class ReadPumpConfigurationAndControlEffectiveOperationMode : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlEffectiveOperationMode()
        : ReadAttribute("effective-operation-mode")
    {
    }

    ~ReadPumpConfigurationAndControlEffectiveOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeEffectiveOperationModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.EffectiveOperationMode response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl EffectiveOperationMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlEffectiveOperationMode : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlEffectiveOperationMode()
        : SubscribeAttribute("effective-operation-mode")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlEffectiveOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEffectiveOperationModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.EffectiveOperationMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EffectiveControlMode
 */
class ReadPumpConfigurationAndControlEffectiveControlMode : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlEffectiveControlMode()
        : ReadAttribute("effective-control-mode")
    {
    }

    ~ReadPumpConfigurationAndControlEffectiveControlMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeEffectiveControlModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.EffectiveControlMode response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl EffectiveControlMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlEffectiveControlMode : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlEffectiveControlMode()
        : SubscribeAttribute("effective-control-mode")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlEffectiveControlMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEffectiveControlModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.EffectiveControlMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Capacity
 */
class ReadPumpConfigurationAndControlCapacity : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlCapacity()
        : ReadAttribute("capacity")
    {
    }

    ~ReadPumpConfigurationAndControlCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeCapacityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.Capacity response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl Capacity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlCapacity : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlCapacity()
        : SubscribeAttribute("capacity")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCapacityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.Capacity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Speed
 */
class ReadPumpConfigurationAndControlSpeed : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlSpeed()
        : ReadAttribute("speed")
    {
    }

    ~ReadPumpConfigurationAndControlSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeSpeedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.Speed response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl Speed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlSpeed : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlSpeed()
        : SubscribeAttribute("speed")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSpeedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.Speed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LifetimeRunningHours
 */
class ReadPumpConfigurationAndControlLifetimeRunningHours : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlLifetimeRunningHours()
        : ReadAttribute("lifetime-running-hours")
    {
    }

    ~ReadPumpConfigurationAndControlLifetimeRunningHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeLifetimeRunningHoursWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.LifetimeRunningHours response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl LifetimeRunningHours read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WritePumpConfigurationAndControlLifetimeRunningHours : public WriteAttribute {
public:
    WritePumpConfigurationAndControlLifetimeRunningHours()
        : WriteAttribute("lifetime-running-hours")
    {
        AddArgument("attr-name", "lifetime-running-hours");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WritePumpConfigurationAndControlLifetimeRunningHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) WriteAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster
            writeAttributeLifetimeRunningHoursWithValue:value
                                                 params:params
                                      completionHandler:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("PumpConfigurationAndControl LifetimeRunningHours write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributePumpConfigurationAndControlLifetimeRunningHours : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlLifetimeRunningHours()
        : SubscribeAttribute("lifetime-running-hours")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlLifetimeRunningHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLifetimeRunningHoursWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.LifetimeRunningHours response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Power
 */
class ReadPumpConfigurationAndControlPower : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlPower()
        : ReadAttribute("power")
    {
    }

    ~ReadPumpConfigurationAndControlPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributePowerWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.Power response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl Power read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlPower : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlPower()
        : SubscribeAttribute("power")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePowerWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.Power response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LifetimeEnergyConsumed
 */
class ReadPumpConfigurationAndControlLifetimeEnergyConsumed : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlLifetimeEnergyConsumed()
        : ReadAttribute("lifetime-energy-consumed")
    {
    }

    ~ReadPumpConfigurationAndControlLifetimeEnergyConsumed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeLifetimeEnergyConsumedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.LifetimeEnergyConsumed response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl LifetimeEnergyConsumed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WritePumpConfigurationAndControlLifetimeEnergyConsumed : public WriteAttribute {
public:
    WritePumpConfigurationAndControlLifetimeEnergyConsumed()
        : WriteAttribute("lifetime-energy-consumed")
    {
        AddArgument("attr-name", "lifetime-energy-consumed");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WritePumpConfigurationAndControlLifetimeEnergyConsumed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) WriteAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster
            writeAttributeLifetimeEnergyConsumedWithValue:value
                                                   params:params
                                        completionHandler:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("PumpConfigurationAndControl LifetimeEnergyConsumed write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributePumpConfigurationAndControlLifetimeEnergyConsumed : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlLifetimeEnergyConsumed()
        : SubscribeAttribute("lifetime-energy-consumed")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlLifetimeEnergyConsumed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLifetimeEnergyConsumedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.LifetimeEnergyConsumed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OperationMode
 */
class ReadPumpConfigurationAndControlOperationMode : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlOperationMode()
        : ReadAttribute("operation-mode")
    {
    }

    ~ReadPumpConfigurationAndControlOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeOperationModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.OperationMode response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl OperationMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WritePumpConfigurationAndControlOperationMode : public WriteAttribute {
public:
    WritePumpConfigurationAndControlOperationMode()
        : WriteAttribute("operation-mode")
    {
        AddArgument("attr-name", "operation-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WritePumpConfigurationAndControlOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) WriteAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOperationModeWithValue:value
                                               params:params
                                    completionHandler:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("PumpConfigurationAndControl OperationMode write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributePumpConfigurationAndControlOperationMode : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlOperationMode()
        : SubscribeAttribute("operation-mode")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOperationModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.OperationMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ControlMode
 */
class ReadPumpConfigurationAndControlControlMode : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlControlMode()
        : ReadAttribute("control-mode")
    {
    }

    ~ReadPumpConfigurationAndControlControlMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeControlModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.ControlMode response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl ControlMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WritePumpConfigurationAndControlControlMode : public WriteAttribute {
public:
    WritePumpConfigurationAndControlControlMode()
        : WriteAttribute("control-mode")
    {
        AddArgument("attr-name", "control-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WritePumpConfigurationAndControlControlMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) WriteAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeControlModeWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("PumpConfigurationAndControl ControlMode write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributePumpConfigurationAndControlControlMode : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlControlMode()
        : SubscribeAttribute("control-mode")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlControlMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeControlModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.ControlMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadPumpConfigurationAndControlGeneratedCommandList : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadPumpConfigurationAndControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadPumpConfigurationAndControlAcceptedCommandList : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadPumpConfigurationAndControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadPumpConfigurationAndControlAttributeList : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadPumpConfigurationAndControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadPumpConfigurationAndControlFeatureMap : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadPumpConfigurationAndControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadPumpConfigurationAndControlClusterRevision : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadPumpConfigurationAndControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Thermostat                                                  | 0x0201 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * SetpointRaiseLower                                                |   0x00 |
| * SetWeeklySchedule                                                 |   0x01 |
| * GetWeeklySchedule                                                 |   0x02 |
| * ClearWeeklySchedule                                               |   0x03 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * LocalTemperature                                                  | 0x0000 |
| * OutdoorTemperature                                                | 0x0001 |
| * Occupancy                                                         | 0x0002 |
| * AbsMinHeatSetpointLimit                                           | 0x0003 |
| * AbsMaxHeatSetpointLimit                                           | 0x0004 |
| * AbsMinCoolSetpointLimit                                           | 0x0005 |
| * AbsMaxCoolSetpointLimit                                           | 0x0006 |
| * PICoolingDemand                                                   | 0x0007 |
| * PIHeatingDemand                                                   | 0x0008 |
| * HVACSystemTypeConfiguration                                       | 0x0009 |
| * LocalTemperatureCalibration                                       | 0x0010 |
| * OccupiedCoolingSetpoint                                           | 0x0011 |
| * OccupiedHeatingSetpoint                                           | 0x0012 |
| * UnoccupiedCoolingSetpoint                                         | 0x0013 |
| * UnoccupiedHeatingSetpoint                                         | 0x0014 |
| * MinHeatSetpointLimit                                              | 0x0015 |
| * MaxHeatSetpointLimit                                              | 0x0016 |
| * MinCoolSetpointLimit                                              | 0x0017 |
| * MaxCoolSetpointLimit                                              | 0x0018 |
| * MinSetpointDeadBand                                               | 0x0019 |
| * RemoteSensing                                                     | 0x001A |
| * ControlSequenceOfOperation                                        | 0x001B |
| * SystemMode                                                        | 0x001C |
| * ThermostatRunningMode                                             | 0x001E |
| * StartOfWeek                                                       | 0x0020 |
| * NumberOfWeeklyTransitions                                         | 0x0021 |
| * NumberOfDailyTransitions                                          | 0x0022 |
| * TemperatureSetpointHold                                           | 0x0023 |
| * TemperatureSetpointHoldDuration                                   | 0x0024 |
| * ThermostatProgrammingOperationMode                                | 0x0025 |
| * ThermostatRunningState                                            | 0x0029 |
| * SetpointChangeSource                                              | 0x0030 |
| * SetpointChangeAmount                                              | 0x0031 |
| * SetpointChangeSourceTimestamp                                     | 0x0032 |
| * OccupiedSetback                                                   | 0x0034 |
| * OccupiedSetbackMin                                                | 0x0035 |
| * OccupiedSetbackMax                                                | 0x0036 |
| * UnoccupiedSetback                                                 | 0x0037 |
| * UnoccupiedSetbackMin                                              | 0x0038 |
| * UnoccupiedSetbackMax                                              | 0x0039 |
| * EmergencyHeatDelta                                                | 0x003A |
| * ACType                                                            | 0x0040 |
| * ACCapacity                                                        | 0x0041 |
| * ACRefrigerantType                                                 | 0x0042 |
| * ACCompressorType                                                  | 0x0043 |
| * ACErrorCode                                                       | 0x0044 |
| * ACLouverPosition                                                  | 0x0045 |
| * ACCoilTemperature                                                 | 0x0046 |
| * ACCapacityformat                                                  | 0x0047 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command SetpointRaiseLower
 */
class ThermostatSetpointRaiseLower : public ClusterCommand {
public:
    ThermostatSetpointRaiseLower()
        : ClusterCommand("setpoint-raise-lower")
    {
        AddArgument("Mode", 0, UINT8_MAX, &mRequest.mode);
        AddArgument("Amount", INT8_MIN, INT8_MAX, &mRequest.amount);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint: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
                                completionHandler:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Thermostat::Commands::SetpointRaiseLower::Type mRequest;
};

/*
 * Command SetWeeklySchedule
 */
class ThermostatSetWeeklySchedule : public ClusterCommand {
public:
    ThermostatSetWeeklySchedule()
        : ClusterCommand("set-weekly-schedule")
        , mComplex_Transitions(&mRequest.transitions)
    {
        AddArgument("NumberOfTransitionsForSequence", 0, UINT8_MAX, &mRequest.numberOfTransitionsForSequence);
        AddArgument("DayOfWeekForSequence", 0, UINT8_MAX, &mRequest.dayOfWeekForSequence);
        AddArgument("ModeForSequence", 0, UINT8_MAX, &mRequest.modeForSequence);
        AddArgument("Transitions", &mComplex_Transitions);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint: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
                               completionHandler:^(NSError * _Nullable error) {
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Thermostat::Commands::SetWeeklySchedule::Type mRequest;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::Thermostat::Structs::ThermostatScheduleTransition::Type>>
        mComplex_Transitions;
};

/*
 * Command GetWeeklySchedule
 */
class ThermostatGetWeeklySchedule : public ClusterCommand {
public:
    ThermostatGetWeeklySchedule()
        : ClusterCommand("get-weekly-schedule")
    {
        AddArgument("DaysToReturn", 0, UINT8_MAX, &mRequest.daysToReturn);
        AddArgument("ModeToReturn", 0, UINT8_MAX, &mRequest.modeToReturn);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint: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
                               completionHandler:^(MTRThermostatClusterGetWeeklyScheduleResponseParams * _Nullable values,
                                   NSError * _Nullable error) {
                                   NSLog(@"Values: %@", values);
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Thermostat::Commands::GetWeeklySchedule::Type mRequest;
};

/*
 * Command ClearWeeklySchedule
 */
class ThermostatClearWeeklySchedule : public ClusterCommand {
public:
    ThermostatClearWeeklySchedule()
        : ClusterCommand("clear-weekly-schedule")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint: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
                                 completionHandler:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute LocalTemperature
 */
class ReadThermostatLocalTemperature : public ReadAttribute {
public:
    ReadThermostatLocalTemperature()
        : ReadAttribute("local-temperature")
    {
    }

    ~ReadThermostatLocalTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeLocalTemperatureWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.LocalTemperature response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat LocalTemperature read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatLocalTemperature : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatLocalTemperature()
        : SubscribeAttribute("local-temperature")
    {
    }

    ~SubscribeAttributeThermostatLocalTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLocalTemperatureWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.LocalTemperature response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OutdoorTemperature
 */
class ReadThermostatOutdoorTemperature : public ReadAttribute {
public:
    ReadThermostatOutdoorTemperature()
        : ReadAttribute("outdoor-temperature")
    {
    }

    ~ReadThermostatOutdoorTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeOutdoorTemperatureWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.OutdoorTemperature response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat OutdoorTemperature read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatOutdoorTemperature : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOutdoorTemperature()
        : SubscribeAttribute("outdoor-temperature")
    {
    }

    ~SubscribeAttributeThermostatOutdoorTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOutdoorTemperatureWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OutdoorTemperature response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Occupancy
 */
class ReadThermostatOccupancy : public ReadAttribute {
public:
    ReadThermostatOccupancy()
        : ReadAttribute("occupancy")
    {
    }

    ~ReadThermostatOccupancy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeOccupancyWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.Occupancy response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat Occupancy read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatOccupancy : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupancy()
        : SubscribeAttribute("occupancy")
    {
    }

    ~SubscribeAttributeThermostatOccupancy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOccupancyWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.Occupancy response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AbsMinHeatSetpointLimit
 */
class ReadThermostatAbsMinHeatSetpointLimit : public ReadAttribute {
public:
    ReadThermostatAbsMinHeatSetpointLimit()
        : ReadAttribute("abs-min-heat-setpoint-limit")
    {
    }

    ~ReadThermostatAbsMinHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeAbsMinHeatSetpointLimitWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMinHeatSetpointLimit response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat AbsMinHeatSetpointLimit read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAbsMinHeatSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAbsMinHeatSetpointLimit()
        : SubscribeAttribute("abs-min-heat-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatAbsMinHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAbsMinHeatSetpointLimitWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMinHeatSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AbsMaxHeatSetpointLimit
 */
class ReadThermostatAbsMaxHeatSetpointLimit : public ReadAttribute {
public:
    ReadThermostatAbsMaxHeatSetpointLimit()
        : ReadAttribute("abs-max-heat-setpoint-limit")
    {
    }

    ~ReadThermostatAbsMaxHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeAbsMaxHeatSetpointLimitWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMaxHeatSetpointLimit response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat AbsMaxHeatSetpointLimit read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAbsMaxHeatSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAbsMaxHeatSetpointLimit()
        : SubscribeAttribute("abs-max-heat-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatAbsMaxHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAbsMaxHeatSetpointLimitWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMaxHeatSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AbsMinCoolSetpointLimit
 */
class ReadThermostatAbsMinCoolSetpointLimit : public ReadAttribute {
public:
    ReadThermostatAbsMinCoolSetpointLimit()
        : ReadAttribute("abs-min-cool-setpoint-limit")
    {
    }

    ~ReadThermostatAbsMinCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeAbsMinCoolSetpointLimitWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMinCoolSetpointLimit response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat AbsMinCoolSetpointLimit read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAbsMinCoolSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAbsMinCoolSetpointLimit()
        : SubscribeAttribute("abs-min-cool-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatAbsMinCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAbsMinCoolSetpointLimitWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMinCoolSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AbsMaxCoolSetpointLimit
 */
class ReadThermostatAbsMaxCoolSetpointLimit : public ReadAttribute {
public:
    ReadThermostatAbsMaxCoolSetpointLimit()
        : ReadAttribute("abs-max-cool-setpoint-limit")
    {
    }

    ~ReadThermostatAbsMaxCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeAbsMaxCoolSetpointLimitWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMaxCoolSetpointLimit response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat AbsMaxCoolSetpointLimit read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAbsMaxCoolSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAbsMaxCoolSetpointLimit()
        : SubscribeAttribute("abs-max-cool-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatAbsMaxCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAbsMaxCoolSetpointLimitWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMaxCoolSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PICoolingDemand
 */
class ReadThermostatPICoolingDemand : public ReadAttribute {
public:
    ReadThermostatPICoolingDemand()
        : ReadAttribute("picooling-demand")
    {
    }

    ~ReadThermostatPICoolingDemand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributePICoolingDemandWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.PICoolingDemand response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat PICoolingDemand read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatPICoolingDemand : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatPICoolingDemand()
        : SubscribeAttribute("picooling-demand")
    {
    }

    ~SubscribeAttributeThermostatPICoolingDemand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePICoolingDemandWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.PICoolingDemand response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PIHeatingDemand
 */
class ReadThermostatPIHeatingDemand : public ReadAttribute {
public:
    ReadThermostatPIHeatingDemand()
        : ReadAttribute("piheating-demand")
    {
    }

    ~ReadThermostatPIHeatingDemand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributePIHeatingDemandWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.PIHeatingDemand response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat PIHeatingDemand read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatPIHeatingDemand : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatPIHeatingDemand()
        : SubscribeAttribute("piheating-demand")
    {
    }

    ~SubscribeAttributeThermostatPIHeatingDemand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePIHeatingDemandWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.PIHeatingDemand response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HVACSystemTypeConfiguration
 */
class ReadThermostatHVACSystemTypeConfiguration : public ReadAttribute {
public:
    ReadThermostatHVACSystemTypeConfiguration()
        : ReadAttribute("hvacsystem-type-configuration")
    {
    }

    ~ReadThermostatHVACSystemTypeConfiguration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeHVACSystemTypeConfigurationWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.HVACSystemTypeConfiguration response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat HVACSystemTypeConfiguration read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatHVACSystemTypeConfiguration : public WriteAttribute {
public:
    WriteThermostatHVACSystemTypeConfiguration()
        : WriteAttribute("hvacsystem-type-configuration")
    {
        AddArgument("attr-name", "hvacsystem-type-configuration");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatHVACSystemTypeConfiguration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeHVACSystemTypeConfigurationWithValue:value
                                                             params:params
                                                  completionHandler:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("Thermostat HVACSystemTypeConfiguration write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatHVACSystemTypeConfiguration : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatHVACSystemTypeConfiguration()
        : SubscribeAttribute("hvacsystem-type-configuration")
    {
    }

    ~SubscribeAttributeThermostatHVACSystemTypeConfiguration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeHVACSystemTypeConfigurationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.HVACSystemTypeConfiguration response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LocalTemperatureCalibration
 */
class ReadThermostatLocalTemperatureCalibration : public ReadAttribute {
public:
    ReadThermostatLocalTemperatureCalibration()
        : ReadAttribute("local-temperature-calibration")
    {
    }

    ~ReadThermostatLocalTemperatureCalibration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeLocalTemperatureCalibrationWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.LocalTemperatureCalibration response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat LocalTemperatureCalibration read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatLocalTemperatureCalibration : public WriteAttribute {
public:
    WriteThermostatLocalTemperatureCalibration()
        : WriteAttribute("local-temperature-calibration")
    {
        AddArgument("attr-name", "local-temperature-calibration");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatLocalTemperatureCalibration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeLocalTemperatureCalibrationWithValue:value
                                                             params:params
                                                  completionHandler:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("Thermostat LocalTemperatureCalibration write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeThermostatLocalTemperatureCalibration : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatLocalTemperatureCalibration()
        : SubscribeAttribute("local-temperature-calibration")
    {
    }

    ~SubscribeAttributeThermostatLocalTemperatureCalibration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLocalTemperatureCalibrationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.LocalTemperatureCalibration response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupiedCoolingSetpoint
 */
class ReadThermostatOccupiedCoolingSetpoint : public ReadAttribute {
public:
    ReadThermostatOccupiedCoolingSetpoint()
        : ReadAttribute("occupied-cooling-setpoint")
    {
    }

    ~ReadThermostatOccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeOccupiedCoolingSetpointWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedCoolingSetpoint response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat OccupiedCoolingSetpoint read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatOccupiedCoolingSetpoint : public WriteAttribute {
public:
    WriteThermostatOccupiedCoolingSetpoint()
        : WriteAttribute("occupied-cooling-setpoint")
    {
        AddArgument("attr-name", "occupied-cooling-setpoint");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatOccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeOccupiedCoolingSetpointWithValue:value
                                                         params:params
                                              completionHandler:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("Thermostat OccupiedCoolingSetpoint write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatOccupiedCoolingSetpoint : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupiedCoolingSetpoint()
        : SubscribeAttribute("occupied-cooling-setpoint")
    {
    }

    ~SubscribeAttributeThermostatOccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOccupiedCoolingSetpointWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedCoolingSetpoint response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupiedHeatingSetpoint
 */
class ReadThermostatOccupiedHeatingSetpoint : public ReadAttribute {
public:
    ReadThermostatOccupiedHeatingSetpoint()
        : ReadAttribute("occupied-heating-setpoint")
    {
    }

    ~ReadThermostatOccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeOccupiedHeatingSetpointWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedHeatingSetpoint response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat OccupiedHeatingSetpoint read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatOccupiedHeatingSetpoint : public WriteAttribute {
public:
    WriteThermostatOccupiedHeatingSetpoint()
        : WriteAttribute("occupied-heating-setpoint")
    {
        AddArgument("attr-name", "occupied-heating-setpoint");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatOccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeOccupiedHeatingSetpointWithValue:value
                                                         params:params
                                              completionHandler:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("Thermostat OccupiedHeatingSetpoint write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatOccupiedHeatingSetpoint : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupiedHeatingSetpoint()
        : SubscribeAttribute("occupied-heating-setpoint")
    {
    }

    ~SubscribeAttributeThermostatOccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOccupiedHeatingSetpointWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedHeatingSetpoint response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UnoccupiedCoolingSetpoint
 */
class ReadThermostatUnoccupiedCoolingSetpoint : public ReadAttribute {
public:
    ReadThermostatUnoccupiedCoolingSetpoint()
        : ReadAttribute("unoccupied-cooling-setpoint")
    {
    }

    ~ReadThermostatUnoccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeUnoccupiedCoolingSetpointWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedCoolingSetpoint response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat UnoccupiedCoolingSetpoint read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUnoccupiedCoolingSetpoint : public WriteAttribute {
public:
    WriteThermostatUnoccupiedCoolingSetpoint()
        : WriteAttribute("unoccupied-cooling-setpoint")
    {
        AddArgument("attr-name", "unoccupied-cooling-setpoint");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUnoccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeUnoccupiedCoolingSetpointWithValue:value
                                                           params:params
                                                completionHandler:^(NSError * _Nullable error) {
                                                    if (error != nil) {
                                                        LogNSError("Thermostat UnoccupiedCoolingSetpoint write Error", error);
                                                    }
                                                    SetCommandExitStatus(error);
                                                }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatUnoccupiedCoolingSetpoint : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUnoccupiedCoolingSetpoint()
        : SubscribeAttribute("unoccupied-cooling-setpoint")
    {
    }

    ~SubscribeAttributeThermostatUnoccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUnoccupiedCoolingSetpointWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedCoolingSetpoint response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UnoccupiedHeatingSetpoint
 */
class ReadThermostatUnoccupiedHeatingSetpoint : public ReadAttribute {
public:
    ReadThermostatUnoccupiedHeatingSetpoint()
        : ReadAttribute("unoccupied-heating-setpoint")
    {
    }

    ~ReadThermostatUnoccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeUnoccupiedHeatingSetpointWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedHeatingSetpoint response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat UnoccupiedHeatingSetpoint read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUnoccupiedHeatingSetpoint : public WriteAttribute {
public:
    WriteThermostatUnoccupiedHeatingSetpoint()
        : WriteAttribute("unoccupied-heating-setpoint")
    {
        AddArgument("attr-name", "unoccupied-heating-setpoint");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUnoccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeUnoccupiedHeatingSetpointWithValue:value
                                                           params:params
                                                completionHandler:^(NSError * _Nullable error) {
                                                    if (error != nil) {
                                                        LogNSError("Thermostat UnoccupiedHeatingSetpoint write Error", error);
                                                    }
                                                    SetCommandExitStatus(error);
                                                }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatUnoccupiedHeatingSetpoint : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUnoccupiedHeatingSetpoint()
        : SubscribeAttribute("unoccupied-heating-setpoint")
    {
    }

    ~SubscribeAttributeThermostatUnoccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUnoccupiedHeatingSetpointWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedHeatingSetpoint response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinHeatSetpointLimit
 */
class ReadThermostatMinHeatSetpointLimit : public ReadAttribute {
public:
    ReadThermostatMinHeatSetpointLimit()
        : ReadAttribute("min-heat-setpoint-limit")
    {
    }

    ~ReadThermostatMinHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeMinHeatSetpointLimitWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.MinHeatSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat MinHeatSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatMinHeatSetpointLimit : public WriteAttribute {
public:
    WriteThermostatMinHeatSetpointLimit()
        : WriteAttribute("min-heat-setpoint-limit")
    {
        AddArgument("attr-name", "min-heat-setpoint-limit");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatMinHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeMinHeatSetpointLimitWithValue:value
                                                      params:params
                                           completionHandler:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("Thermostat MinHeatSetpointLimit write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatMinHeatSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatMinHeatSetpointLimit()
        : SubscribeAttribute("min-heat-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatMinHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinHeatSetpointLimitWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.MinHeatSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxHeatSetpointLimit
 */
class ReadThermostatMaxHeatSetpointLimit : public ReadAttribute {
public:
    ReadThermostatMaxHeatSetpointLimit()
        : ReadAttribute("max-heat-setpoint-limit")
    {
    }

    ~ReadThermostatMaxHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeMaxHeatSetpointLimitWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.MaxHeatSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat MaxHeatSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatMaxHeatSetpointLimit : public WriteAttribute {
public:
    WriteThermostatMaxHeatSetpointLimit()
        : WriteAttribute("max-heat-setpoint-limit")
    {
        AddArgument("attr-name", "max-heat-setpoint-limit");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatMaxHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeMaxHeatSetpointLimitWithValue:value
                                                      params:params
                                           completionHandler:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("Thermostat MaxHeatSetpointLimit write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatMaxHeatSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatMaxHeatSetpointLimit()
        : SubscribeAttribute("max-heat-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatMaxHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxHeatSetpointLimitWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.MaxHeatSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinCoolSetpointLimit
 */
class ReadThermostatMinCoolSetpointLimit : public ReadAttribute {
public:
    ReadThermostatMinCoolSetpointLimit()
        : ReadAttribute("min-cool-setpoint-limit")
    {
    }

    ~ReadThermostatMinCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeMinCoolSetpointLimitWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.MinCoolSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat MinCoolSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatMinCoolSetpointLimit : public WriteAttribute {
public:
    WriteThermostatMinCoolSetpointLimit()
        : WriteAttribute("min-cool-setpoint-limit")
    {
        AddArgument("attr-name", "min-cool-setpoint-limit");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatMinCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeMinCoolSetpointLimitWithValue:value
                                                      params:params
                                           completionHandler:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("Thermostat MinCoolSetpointLimit write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatMinCoolSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatMinCoolSetpointLimit()
        : SubscribeAttribute("min-cool-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatMinCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinCoolSetpointLimitWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.MinCoolSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxCoolSetpointLimit
 */
class ReadThermostatMaxCoolSetpointLimit : public ReadAttribute {
public:
    ReadThermostatMaxCoolSetpointLimit()
        : ReadAttribute("max-cool-setpoint-limit")
    {
    }

    ~ReadThermostatMaxCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeMaxCoolSetpointLimitWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.MaxCoolSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat MaxCoolSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatMaxCoolSetpointLimit : public WriteAttribute {
public:
    WriteThermostatMaxCoolSetpointLimit()
        : WriteAttribute("max-cool-setpoint-limit")
    {
        AddArgument("attr-name", "max-cool-setpoint-limit");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatMaxCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeMaxCoolSetpointLimitWithValue:value
                                                      params:params
                                           completionHandler:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("Thermostat MaxCoolSetpointLimit write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatMaxCoolSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatMaxCoolSetpointLimit()
        : SubscribeAttribute("max-cool-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatMaxCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxCoolSetpointLimitWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.MaxCoolSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinSetpointDeadBand
 */
class ReadThermostatMinSetpointDeadBand : public ReadAttribute {
public:
    ReadThermostatMinSetpointDeadBand()
        : ReadAttribute("min-setpoint-dead-band")
    {
    }

    ~ReadThermostatMinSetpointDeadBand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeMinSetpointDeadBandWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.MinSetpointDeadBand response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat MinSetpointDeadBand read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatMinSetpointDeadBand : public WriteAttribute {
public:
    WriteThermostatMinSetpointDeadBand()
        : WriteAttribute("min-setpoint-dead-band")
    {
        AddArgument("attr-name", "min-setpoint-dead-band");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatMinSetpointDeadBand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeMinSetpointDeadBandWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("Thermostat MinSetpointDeadBand write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeThermostatMinSetpointDeadBand : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatMinSetpointDeadBand()
        : SubscribeAttribute("min-setpoint-dead-band")
    {
    }

    ~SubscribeAttributeThermostatMinSetpointDeadBand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinSetpointDeadBandWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.MinSetpointDeadBand response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RemoteSensing
 */
class ReadThermostatRemoteSensing : public ReadAttribute {
public:
    ReadThermostatRemoteSensing()
        : ReadAttribute("remote-sensing")
    {
    }

    ~ReadThermostatRemoteSensing() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeRemoteSensingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.RemoteSensing response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat RemoteSensing read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatRemoteSensing : public WriteAttribute {
public:
    WriteThermostatRemoteSensing()
        : WriteAttribute("remote-sensing")
    {
        AddArgument("attr-name", "remote-sensing");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatRemoteSensing() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeRemoteSensingWithValue:value
                                               params:params
                                    completionHandler:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("Thermostat RemoteSensing write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatRemoteSensing : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatRemoteSensing()
        : SubscribeAttribute("remote-sensing")
    {
    }

    ~SubscribeAttributeThermostatRemoteSensing() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRemoteSensingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.RemoteSensing response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ControlSequenceOfOperation
 */
class ReadThermostatControlSequenceOfOperation : public ReadAttribute {
public:
    ReadThermostatControlSequenceOfOperation()
        : ReadAttribute("control-sequence-of-operation")
    {
    }

    ~ReadThermostatControlSequenceOfOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeControlSequenceOfOperationWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ControlSequenceOfOperation response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat ControlSequenceOfOperation read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatControlSequenceOfOperation : public WriteAttribute {
public:
    WriteThermostatControlSequenceOfOperation()
        : WriteAttribute("control-sequence-of-operation")
    {
        AddArgument("attr-name", "control-sequence-of-operation");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatControlSequenceOfOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeControlSequenceOfOperationWithValue:value
                                                            params:params
                                                 completionHandler:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("Thermostat ControlSequenceOfOperation write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatControlSequenceOfOperation : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatControlSequenceOfOperation()
        : SubscribeAttribute("control-sequence-of-operation")
    {
    }

    ~SubscribeAttributeThermostatControlSequenceOfOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeControlSequenceOfOperationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ControlSequenceOfOperation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SystemMode
 */
class ReadThermostatSystemMode : public ReadAttribute {
public:
    ReadThermostatSystemMode()
        : ReadAttribute("system-mode")
    {
    }

    ~ReadThermostatSystemMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeSystemModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.SystemMode response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat SystemMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatSystemMode : public WriteAttribute {
public:
    WriteThermostatSystemMode()
        : WriteAttribute("system-mode")
    {
        AddArgument("attr-name", "system-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatSystemMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeSystemModeWithValue:value
                                            params:params
                                 completionHandler:^(NSError * _Nullable error) {
                                     if (error != nil) {
                                         LogNSError("Thermostat SystemMode write Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatSystemMode : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatSystemMode()
        : SubscribeAttribute("system-mode")
    {
    }

    ~SubscribeAttributeThermostatSystemMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSystemModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.SystemMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ThermostatRunningMode
 */
class ReadThermostatThermostatRunningMode : public ReadAttribute {
public:
    ReadThermostatThermostatRunningMode()
        : ReadAttribute("thermostat-running-mode")
    {
    }

    ~ReadThermostatThermostatRunningMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000001E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeThermostatRunningModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ThermostatRunningMode response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ThermostatRunningMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatThermostatRunningMode : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatThermostatRunningMode()
        : SubscribeAttribute("thermostat-running-mode")
    {
    }

    ~SubscribeAttributeThermostatThermostatRunningMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000001E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeThermostatRunningModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ThermostatRunningMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StartOfWeek
 */
class ReadThermostatStartOfWeek : public ReadAttribute {
public:
    ReadThermostatStartOfWeek()
        : ReadAttribute("start-of-week")
    {
    }

    ~ReadThermostatStartOfWeek() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeStartOfWeekWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.StartOfWeek response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat StartOfWeek read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatStartOfWeek : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatStartOfWeek()
        : SubscribeAttribute("start-of-week")
    {
    }

    ~SubscribeAttributeThermostatStartOfWeek() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeStartOfWeekWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.StartOfWeek response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfWeeklyTransitions
 */
class ReadThermostatNumberOfWeeklyTransitions : public ReadAttribute {
public:
    ReadThermostatNumberOfWeeklyTransitions()
        : ReadAttribute("number-of-weekly-transitions")
    {
    }

    ~ReadThermostatNumberOfWeeklyTransitions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeNumberOfWeeklyTransitionsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.NumberOfWeeklyTransitions response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat NumberOfWeeklyTransitions read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatNumberOfWeeklyTransitions : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatNumberOfWeeklyTransitions()
        : SubscribeAttribute("number-of-weekly-transitions")
    {
    }

    ~SubscribeAttributeThermostatNumberOfWeeklyTransitions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfWeeklyTransitionsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.NumberOfWeeklyTransitions response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfDailyTransitions
 */
class ReadThermostatNumberOfDailyTransitions : public ReadAttribute {
public:
    ReadThermostatNumberOfDailyTransitions()
        : ReadAttribute("number-of-daily-transitions")
    {
    }

    ~ReadThermostatNumberOfDailyTransitions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeNumberOfDailyTransitionsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.NumberOfDailyTransitions response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat NumberOfDailyTransitions read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatNumberOfDailyTransitions : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatNumberOfDailyTransitions()
        : SubscribeAttribute("number-of-daily-transitions")
    {
    }

    ~SubscribeAttributeThermostatNumberOfDailyTransitions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfDailyTransitionsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.NumberOfDailyTransitions response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TemperatureSetpointHold
 */
class ReadThermostatTemperatureSetpointHold : public ReadAttribute {
public:
    ReadThermostatTemperatureSetpointHold()
        : ReadAttribute("temperature-setpoint-hold")
    {
    }

    ~ReadThermostatTemperatureSetpointHold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000023) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeTemperatureSetpointHoldWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.TemperatureSetpointHold response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat TemperatureSetpointHold read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatTemperatureSetpointHold : public WriteAttribute {
public:
    WriteThermostatTemperatureSetpointHold()
        : WriteAttribute("temperature-setpoint-hold")
    {
        AddArgument("attr-name", "temperature-setpoint-hold");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatTemperatureSetpointHold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeTemperatureSetpointHoldWithValue:value
                                                         params:params
                                              completionHandler:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("Thermostat TemperatureSetpointHold write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatTemperatureSetpointHold : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatTemperatureSetpointHold()
        : SubscribeAttribute("temperature-setpoint-hold")
    {
    }

    ~SubscribeAttributeThermostatTemperatureSetpointHold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTemperatureSetpointHoldWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.TemperatureSetpointHold response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TemperatureSetpointHoldDuration
 */
class ReadThermostatTemperatureSetpointHoldDuration : public ReadAttribute {
public:
    ReadThermostatTemperatureSetpointHoldDuration()
        : ReadAttribute("temperature-setpoint-hold-duration")
    {
    }

    ~ReadThermostatTemperatureSetpointHoldDuration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeTemperatureSetpointHoldDurationWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.TemperatureSetpointHoldDuration response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat TemperatureSetpointHoldDuration read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatTemperatureSetpointHoldDuration : public WriteAttribute {
public:
    WriteThermostatTemperatureSetpointHoldDuration()
        : WriteAttribute("temperature-setpoint-hold-duration")
    {
        AddArgument("attr-name", "temperature-setpoint-hold-duration");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatTemperatureSetpointHoldDuration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeTemperatureSetpointHoldDurationWithValue:value
                                                                 params:params
                                                      completionHandler:^(NSError * _Nullable error) {
                                                          if (error != nil) {
                                                              LogNSError(
                                                                  "Thermostat TemperatureSetpointHoldDuration write Error", error);
                                                          }
                                                          SetCommandExitStatus(error);
                                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeThermostatTemperatureSetpointHoldDuration : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatTemperatureSetpointHoldDuration()
        : SubscribeAttribute("temperature-setpoint-hold-duration")
    {
    }

    ~SubscribeAttributeThermostatTemperatureSetpointHoldDuration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTemperatureSetpointHoldDurationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.TemperatureSetpointHoldDuration response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ThermostatProgrammingOperationMode
 */
class ReadThermostatThermostatProgrammingOperationMode : public ReadAttribute {
public:
    ReadThermostatThermostatProgrammingOperationMode()
        : ReadAttribute("thermostat-programming-operation-mode")
    {
    }

    ~ReadThermostatThermostatProgrammingOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeThermostatProgrammingOperationModeWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ThermostatProgrammingOperationMode response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ThermostatProgrammingOperationMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatThermostatProgrammingOperationMode : public WriteAttribute {
public:
    WriteThermostatThermostatProgrammingOperationMode()
        : WriteAttribute("thermostat-programming-operation-mode")
    {
        AddArgument("attr-name", "thermostat-programming-operation-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatThermostatProgrammingOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster
            writeAttributeThermostatProgrammingOperationModeWithValue:value
                                                               params:params
                                                    completionHandler:^(NSError * _Nullable error) {
                                                        if (error != nil) {
                                                            LogNSError(
                                                                "Thermostat ThermostatProgrammingOperationMode write Error", error);
                                                        }
                                                        SetCommandExitStatus(error);
                                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatThermostatProgrammingOperationMode : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatThermostatProgrammingOperationMode()
        : SubscribeAttribute("thermostat-programming-operation-mode")
    {
    }

    ~SubscribeAttributeThermostatThermostatProgrammingOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeThermostatProgrammingOperationModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ThermostatProgrammingOperationMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ThermostatRunningState
 */
class ReadThermostatThermostatRunningState : public ReadAttribute {
public:
    ReadThermostatThermostatRunningState()
        : ReadAttribute("thermostat-running-state")
    {
    }

    ~ReadThermostatThermostatRunningState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeThermostatRunningStateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ThermostatRunningState response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ThermostatRunningState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatThermostatRunningState : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatThermostatRunningState()
        : SubscribeAttribute("thermostat-running-state")
    {
    }

    ~SubscribeAttributeThermostatThermostatRunningState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeThermostatRunningStateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ThermostatRunningState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SetpointChangeSource
 */
class ReadThermostatSetpointChangeSource : public ReadAttribute {
public:
    ReadThermostatSetpointChangeSource()
        : ReadAttribute("setpoint-change-source")
    {
    }

    ~ReadThermostatSetpointChangeSource() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeSetpointChangeSourceWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.SetpointChangeSource response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat SetpointChangeSource read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatSetpointChangeSource : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatSetpointChangeSource()
        : SubscribeAttribute("setpoint-change-source")
    {
    }

    ~SubscribeAttributeThermostatSetpointChangeSource() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSetpointChangeSourceWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.SetpointChangeSource response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SetpointChangeAmount
 */
class ReadThermostatSetpointChangeAmount : public ReadAttribute {
public:
    ReadThermostatSetpointChangeAmount()
        : ReadAttribute("setpoint-change-amount")
    {
    }

    ~ReadThermostatSetpointChangeAmount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeSetpointChangeAmountWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.SetpointChangeAmount response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat SetpointChangeAmount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatSetpointChangeAmount : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatSetpointChangeAmount()
        : SubscribeAttribute("setpoint-change-amount")
    {
    }

    ~SubscribeAttributeThermostatSetpointChangeAmount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSetpointChangeAmountWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.SetpointChangeAmount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SetpointChangeSourceTimestamp
 */
class ReadThermostatSetpointChangeSourceTimestamp : public ReadAttribute {
public:
    ReadThermostatSetpointChangeSourceTimestamp()
        : ReadAttribute("setpoint-change-source-timestamp")
    {
    }

    ~ReadThermostatSetpointChangeSourceTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeSetpointChangeSourceTimestampWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.SetpointChangeSourceTimestamp response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat SetpointChangeSourceTimestamp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatSetpointChangeSourceTimestamp : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatSetpointChangeSourceTimestamp()
        : SubscribeAttribute("setpoint-change-source-timestamp")
    {
    }

    ~SubscribeAttributeThermostatSetpointChangeSourceTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSetpointChangeSourceTimestampWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.SetpointChangeSourceTimestamp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupiedSetback
 */
class ReadThermostatOccupiedSetback : public ReadAttribute {
public:
    ReadThermostatOccupiedSetback()
        : ReadAttribute("occupied-setback")
    {
    }

    ~ReadThermostatOccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000034) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeOccupiedSetbackWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.OccupiedSetback response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat OccupiedSetback read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatOccupiedSetback : public WriteAttribute {
public:
    WriteThermostatOccupiedSetback()
        : WriteAttribute("occupied-setback")
    {
        AddArgument("attr-name", "occupied-setback");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatOccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOccupiedSetbackWithValue:value
                                                 params:params
                                      completionHandler:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("Thermostat OccupiedSetback write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatOccupiedSetback : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupiedSetback()
        : SubscribeAttribute("occupied-setback")
    {
    }

    ~SubscribeAttributeThermostatOccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOccupiedSetbackWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedSetback response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupiedSetbackMin
 */
class ReadThermostatOccupiedSetbackMin : public ReadAttribute {
public:
    ReadThermostatOccupiedSetbackMin()
        : ReadAttribute("occupied-setback-min")
    {
    }

    ~ReadThermostatOccupiedSetbackMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000035) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeOccupiedSetbackMinWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.OccupiedSetbackMin response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat OccupiedSetbackMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatOccupiedSetbackMin : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupiedSetbackMin()
        : SubscribeAttribute("occupied-setback-min")
    {
    }

    ~SubscribeAttributeThermostatOccupiedSetbackMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOccupiedSetbackMinWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedSetbackMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupiedSetbackMax
 */
class ReadThermostatOccupiedSetbackMax : public ReadAttribute {
public:
    ReadThermostatOccupiedSetbackMax()
        : ReadAttribute("occupied-setback-max")
    {
    }

    ~ReadThermostatOccupiedSetbackMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000036) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeOccupiedSetbackMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.OccupiedSetbackMax response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat OccupiedSetbackMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatOccupiedSetbackMax : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupiedSetbackMax()
        : SubscribeAttribute("occupied-setback-max")
    {
    }

    ~SubscribeAttributeThermostatOccupiedSetbackMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000036) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOccupiedSetbackMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedSetbackMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UnoccupiedSetback
 */
class ReadThermostatUnoccupiedSetback : public ReadAttribute {
public:
    ReadThermostatUnoccupiedSetback()
        : ReadAttribute("unoccupied-setback")
    {
    }

    ~ReadThermostatUnoccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000037) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeUnoccupiedSetbackWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.UnoccupiedSetback response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat UnoccupiedSetback read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUnoccupiedSetback : public WriteAttribute {
public:
    WriteThermostatUnoccupiedSetback()
        : WriteAttribute("unoccupied-setback")
    {
        AddArgument("attr-name", "unoccupied-setback");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUnoccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000037) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeUnoccupiedSetbackWithValue:value
                                                   params:params
                                        completionHandler:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("Thermostat UnoccupiedSetback write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatUnoccupiedSetback : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUnoccupiedSetback()
        : SubscribeAttribute("unoccupied-setback")
    {
    }

    ~SubscribeAttributeThermostatUnoccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000037) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUnoccupiedSetbackWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedSetback response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UnoccupiedSetbackMin
 */
class ReadThermostatUnoccupiedSetbackMin : public ReadAttribute {
public:
    ReadThermostatUnoccupiedSetbackMin()
        : ReadAttribute("unoccupied-setback-min")
    {
    }

    ~ReadThermostatUnoccupiedSetbackMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000038) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeUnoccupiedSetbackMinWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.UnoccupiedSetbackMin response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat UnoccupiedSetbackMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUnoccupiedSetbackMin : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUnoccupiedSetbackMin()
        : SubscribeAttribute("unoccupied-setback-min")
    {
    }

    ~SubscribeAttributeThermostatUnoccupiedSetbackMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000038) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUnoccupiedSetbackMinWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedSetbackMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UnoccupiedSetbackMax
 */
class ReadThermostatUnoccupiedSetbackMax : public ReadAttribute {
public:
    ReadThermostatUnoccupiedSetbackMax()
        : ReadAttribute("unoccupied-setback-max")
    {
    }

    ~ReadThermostatUnoccupiedSetbackMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000039) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeUnoccupiedSetbackMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.UnoccupiedSetbackMax response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat UnoccupiedSetbackMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUnoccupiedSetbackMax : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUnoccupiedSetbackMax()
        : SubscribeAttribute("unoccupied-setback-max")
    {
    }

    ~SubscribeAttributeThermostatUnoccupiedSetbackMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000039) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUnoccupiedSetbackMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedSetbackMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EmergencyHeatDelta
 */
class ReadThermostatEmergencyHeatDelta : public ReadAttribute {
public:
    ReadThermostatEmergencyHeatDelta()
        : ReadAttribute("emergency-heat-delta")
    {
    }

    ~ReadThermostatEmergencyHeatDelta() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000003A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeEmergencyHeatDeltaWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.EmergencyHeatDelta response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat EmergencyHeatDelta read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatEmergencyHeatDelta : public WriteAttribute {
public:
    WriteThermostatEmergencyHeatDelta()
        : WriteAttribute("emergency-heat-delta")
    {
        AddArgument("attr-name", "emergency-heat-delta");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatEmergencyHeatDelta() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x0000003A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeEmergencyHeatDeltaWithValue:value
                                                    params:params
                                         completionHandler:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("Thermostat EmergencyHeatDelta write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatEmergencyHeatDelta : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatEmergencyHeatDelta()
        : SubscribeAttribute("emergency-heat-delta")
    {
    }

    ~SubscribeAttributeThermostatEmergencyHeatDelta() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000003A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEmergencyHeatDeltaWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.EmergencyHeatDelta response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACType
 */
class ReadThermostatACType : public ReadAttribute {
public:
    ReadThermostatACType()
        : ReadAttribute("actype")
    {
    }

    ~ReadThermostatACType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000040) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeACTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACType response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACType : public WriteAttribute {
public:
    WriteThermostatACType()
        : WriteAttribute("actype")
    {
        AddArgument("attr-name", "actype");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000040) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeACTypeWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("Thermostat ACType write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatACType : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACType()
        : SubscribeAttribute("actype")
    {
    }

    ~SubscribeAttributeThermostatACType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000040) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeACTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACCapacity
 */
class ReadThermostatACCapacity : public ReadAttribute {
public:
    ReadThermostatACCapacity()
        : ReadAttribute("accapacity")
    {
    }

    ~ReadThermostatACCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000041) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeACCapacityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACCapacity response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACCapacity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACCapacity : public WriteAttribute {
public:
    WriteThermostatACCapacity()
        : WriteAttribute("accapacity")
    {
        AddArgument("attr-name", "accapacity");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000041) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeACCapacityWithValue:value
                                            params:params
                                 completionHandler:^(NSError * _Nullable error) {
                                     if (error != nil) {
                                         LogNSError("Thermostat ACCapacity write Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeThermostatACCapacity : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACCapacity()
        : SubscribeAttribute("accapacity")
    {
    }

    ~SubscribeAttributeThermostatACCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000041) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeACCapacityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACCapacity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACRefrigerantType
 */
class ReadThermostatACRefrigerantType : public ReadAttribute {
public:
    ReadThermostatACRefrigerantType()
        : ReadAttribute("acrefrigerant-type")
    {
    }

    ~ReadThermostatACRefrigerantType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000042) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeACRefrigerantTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACRefrigerantType response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACRefrigerantType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACRefrigerantType : public WriteAttribute {
public:
    WriteThermostatACRefrigerantType()
        : WriteAttribute("acrefrigerant-type")
    {
        AddArgument("attr-name", "acrefrigerant-type");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACRefrigerantType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000042) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeACRefrigerantTypeWithValue:value
                                                   params:params
                                        completionHandler:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("Thermostat ACRefrigerantType write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatACRefrigerantType : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACRefrigerantType()
        : SubscribeAttribute("acrefrigerant-type")
    {
    }

    ~SubscribeAttributeThermostatACRefrigerantType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000042) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeACRefrigerantTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACRefrigerantType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACCompressorType
 */
class ReadThermostatACCompressorType : public ReadAttribute {
public:
    ReadThermostatACCompressorType()
        : ReadAttribute("accompressor-type")
    {
    }

    ~ReadThermostatACCompressorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000043) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeACCompressorTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACCompressorType response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACCompressorType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACCompressorType : public WriteAttribute {
public:
    WriteThermostatACCompressorType()
        : WriteAttribute("accompressor-type")
    {
        AddArgument("attr-name", "accompressor-type");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACCompressorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000043) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeACCompressorTypeWithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("Thermostat ACCompressorType write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatACCompressorType : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACCompressorType()
        : SubscribeAttribute("accompressor-type")
    {
    }

    ~SubscribeAttributeThermostatACCompressorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000043) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeACCompressorTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACCompressorType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACErrorCode
 */
class ReadThermostatACErrorCode : public ReadAttribute {
public:
    ReadThermostatACErrorCode()
        : ReadAttribute("acerror-code")
    {
    }

    ~ReadThermostatACErrorCode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000044) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeACErrorCodeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACErrorCode response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACErrorCode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACErrorCode : public WriteAttribute {
public:
    WriteThermostatACErrorCode()
        : WriteAttribute("acerror-code")
    {
        AddArgument("attr-name", "acerror-code");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACErrorCode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000044) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeACErrorCodeWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("Thermostat ACErrorCode write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeThermostatACErrorCode : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACErrorCode()
        : SubscribeAttribute("acerror-code")
    {
    }

    ~SubscribeAttributeThermostatACErrorCode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000044) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeACErrorCodeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACErrorCode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACLouverPosition
 */
class ReadThermostatACLouverPosition : public ReadAttribute {
public:
    ReadThermostatACLouverPosition()
        : ReadAttribute("aclouver-position")
    {
    }

    ~ReadThermostatACLouverPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000045) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeACLouverPositionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACLouverPosition response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACLouverPosition read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACLouverPosition : public WriteAttribute {
public:
    WriteThermostatACLouverPosition()
        : WriteAttribute("aclouver-position")
    {
        AddArgument("attr-name", "aclouver-position");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACLouverPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000045) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeACLouverPositionWithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("Thermostat ACLouverPosition write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatACLouverPosition : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACLouverPosition()
        : SubscribeAttribute("aclouver-position")
    {
    }

    ~SubscribeAttributeThermostatACLouverPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000045) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeACLouverPositionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACLouverPosition response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACCoilTemperature
 */
class ReadThermostatACCoilTemperature : public ReadAttribute {
public:
    ReadThermostatACCoilTemperature()
        : ReadAttribute("accoil-temperature")
    {
    }

    ~ReadThermostatACCoilTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000046) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeACCoilTemperatureWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACCoilTemperature response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACCoilTemperature read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatACCoilTemperature : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACCoilTemperature()
        : SubscribeAttribute("accoil-temperature")
    {
    }

    ~SubscribeAttributeThermostatACCoilTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000046) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeACCoilTemperatureWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACCoilTemperature response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACCapacityformat
 */
class ReadThermostatACCapacityformat : public ReadAttribute {
public:
    ReadThermostatACCapacityformat()
        : ReadAttribute("accapacityformat")
    {
    }

    ~ReadThermostatACCapacityformat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000047) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeACCapacityformatWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACCapacityformat response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACCapacityformat read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACCapacityformat : public WriteAttribute {
public:
    WriteThermostatACCapacityformat()
        : WriteAttribute("accapacityformat")
    {
        AddArgument("attr-name", "accapacityformat");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACCapacityformat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000047) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeACCapacityformatWithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("Thermostat ACCapacityformat write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatACCapacityformat : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACCapacityformat()
        : SubscribeAttribute("accapacityformat")
    {
    }

    ~SubscribeAttributeThermostatACCapacityformat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000047) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeACCapacityformatWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACCapacityformat response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadThermostatGeneratedCommandList : public ReadAttribute {
public:
    ReadThermostatGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadThermostatGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeThermostatGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadThermostatAcceptedCommandList : public ReadAttribute {
public:
    ReadThermostatAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadThermostatAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeThermostatAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadThermostatAttributeList : public ReadAttribute {
public:
    ReadThermostatAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadThermostatAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeThermostatAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadThermostatFeatureMap : public ReadAttribute {
public:
    ReadThermostatFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadThermostatFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeThermostatFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadThermostatClusterRevision : public ReadAttribute {
public:
    ReadThermostatClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadThermostatClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeThermostatClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster FanControl                                                  | 0x0202 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * FanMode                                                           | 0x0000 |
| * FanModeSequence                                                   | 0x0001 |
| * PercentSetting                                                    | 0x0002 |
| * PercentCurrent                                                    | 0x0003 |
| * SpeedMax                                                          | 0x0004 |
| * SpeedSetting                                                      | 0x0005 |
| * SpeedCurrent                                                      | 0x0006 |
| * RockSupport                                                       | 0x0007 |
| * RockSetting                                                       | 0x0008 |
| * WindSupport                                                       | 0x0009 |
| * WindSetting                                                       | 0x000A |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute FanMode
 */
class ReadFanControlFanMode : public ReadAttribute {
public:
    ReadFanControlFanMode()
        : ReadAttribute("fan-mode")
    {
    }

    ~ReadFanControlFanMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeFanModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.FanMode response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl FanMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlFanMode : public WriteAttribute {
public:
    WriteFanControlFanMode()
        : WriteAttribute("fan-mode")
    {
        AddArgument("attr-name", "fan-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlFanMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeFanModeWithValue:value
                                         params:params
                              completionHandler:^(NSError * _Nullable error) {
                                  if (error != nil) {
                                      LogNSError("FanControl FanMode write Error", error);
                                  }
                                  SetCommandExitStatus(error);
                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlFanMode : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlFanMode()
        : SubscribeAttribute("fan-mode")
    {
    }

    ~SubscribeAttributeFanControlFanMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFanModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.FanMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FanModeSequence
 */
class ReadFanControlFanModeSequence : public ReadAttribute {
public:
    ReadFanControlFanModeSequence()
        : ReadAttribute("fan-mode-sequence")
    {
    }

    ~ReadFanControlFanModeSequence() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeFanModeSequenceWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.FanModeSequence response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl FanModeSequence read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlFanModeSequence : public WriteAttribute {
public:
    WriteFanControlFanModeSequence()
        : WriteAttribute("fan-mode-sequence")
    {
        AddArgument("attr-name", "fan-mode-sequence");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlFanModeSequence() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeFanModeSequenceWithValue:value
                                                 params:params
                                      completionHandler:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("FanControl FanModeSequence write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlFanModeSequence : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlFanModeSequence()
        : SubscribeAttribute("fan-mode-sequence")
    {
    }

    ~SubscribeAttributeFanControlFanModeSequence() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFanModeSequenceWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.FanModeSequence response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PercentSetting
 */
class ReadFanControlPercentSetting : public ReadAttribute {
public:
    ReadFanControlPercentSetting()
        : ReadAttribute("percent-setting")
    {
    }

    ~ReadFanControlPercentSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributePercentSettingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.PercentSetting response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl PercentSetting read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlPercentSetting : public WriteAttribute {
public:
    WriteFanControlPercentSetting()
        : WriteAttribute("percent-setting")
    {
        AddArgument("attr-name", "percent-setting");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlPercentSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributePercentSettingWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("FanControl PercentSetting write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlPercentSetting : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlPercentSetting()
        : SubscribeAttribute("percent-setting")
    {
    }

    ~SubscribeAttributeFanControlPercentSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePercentSettingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.PercentSetting response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PercentCurrent
 */
class ReadFanControlPercentCurrent : public ReadAttribute {
public:
    ReadFanControlPercentCurrent()
        : ReadAttribute("percent-current")
    {
    }

    ~ReadFanControlPercentCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributePercentCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.PercentCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl PercentCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlPercentCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlPercentCurrent()
        : SubscribeAttribute("percent-current")
    {
    }

    ~SubscribeAttributeFanControlPercentCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePercentCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.PercentCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SpeedMax
 */
class ReadFanControlSpeedMax : public ReadAttribute {
public:
    ReadFanControlSpeedMax()
        : ReadAttribute("speed-max")
    {
    }

    ~ReadFanControlSpeedMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeSpeedMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.SpeedMax response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl SpeedMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlSpeedMax : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlSpeedMax()
        : SubscribeAttribute("speed-max")
    {
    }

    ~SubscribeAttributeFanControlSpeedMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSpeedMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.SpeedMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SpeedSetting
 */
class ReadFanControlSpeedSetting : public ReadAttribute {
public:
    ReadFanControlSpeedSetting()
        : ReadAttribute("speed-setting")
    {
    }

    ~ReadFanControlSpeedSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeSpeedSettingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.SpeedSetting response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl SpeedSetting read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlSpeedSetting : public WriteAttribute {
public:
    WriteFanControlSpeedSetting()
        : WriteAttribute("speed-setting")
    {
        AddArgument("attr-name", "speed-setting");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlSpeedSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeSpeedSettingWithValue:value
                                              params:params
                                   completionHandler:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("FanControl SpeedSetting write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlSpeedSetting : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlSpeedSetting()
        : SubscribeAttribute("speed-setting")
    {
    }

    ~SubscribeAttributeFanControlSpeedSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSpeedSettingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.SpeedSetting response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SpeedCurrent
 */
class ReadFanControlSpeedCurrent : public ReadAttribute {
public:
    ReadFanControlSpeedCurrent()
        : ReadAttribute("speed-current")
    {
    }

    ~ReadFanControlSpeedCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeSpeedCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.SpeedCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl SpeedCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlSpeedCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlSpeedCurrent()
        : SubscribeAttribute("speed-current")
    {
    }

    ~SubscribeAttributeFanControlSpeedCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSpeedCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.SpeedCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RockSupport
 */
class ReadFanControlRockSupport : public ReadAttribute {
public:
    ReadFanControlRockSupport()
        : ReadAttribute("rock-support")
    {
    }

    ~ReadFanControlRockSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeRockSupportWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.RockSupport response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl RockSupport read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlRockSupport : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlRockSupport()
        : SubscribeAttribute("rock-support")
    {
    }

    ~SubscribeAttributeFanControlRockSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRockSupportWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.RockSupport response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RockSetting
 */
class ReadFanControlRockSetting : public ReadAttribute {
public:
    ReadFanControlRockSetting()
        : ReadAttribute("rock-setting")
    {
    }

    ~ReadFanControlRockSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeRockSettingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.RockSetting response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl RockSetting read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlRockSetting : public WriteAttribute {
public:
    WriteFanControlRockSetting()
        : WriteAttribute("rock-setting")
    {
        AddArgument("attr-name", "rock-setting");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlRockSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeRockSettingWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("FanControl RockSetting write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlRockSetting : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlRockSetting()
        : SubscribeAttribute("rock-setting")
    {
    }

    ~SubscribeAttributeFanControlRockSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRockSettingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.RockSetting response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WindSupport
 */
class ReadFanControlWindSupport : public ReadAttribute {
public:
    ReadFanControlWindSupport()
        : ReadAttribute("wind-support")
    {
    }

    ~ReadFanControlWindSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeWindSupportWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.WindSupport response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl WindSupport read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlWindSupport : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlWindSupport()
        : SubscribeAttribute("wind-support")
    {
    }

    ~SubscribeAttributeFanControlWindSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWindSupportWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.WindSupport response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WindSetting
 */
class ReadFanControlWindSetting : public ReadAttribute {
public:
    ReadFanControlWindSetting()
        : ReadAttribute("wind-setting")
    {
    }

    ~ReadFanControlWindSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeWindSettingWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.WindSetting response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl WindSetting read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlWindSetting : public WriteAttribute {
public:
    WriteFanControlWindSetting()
        : WriteAttribute("wind-setting")
    {
        AddArgument("attr-name", "wind-setting");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlWindSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeWindSettingWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("FanControl WindSetting write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlWindSetting : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlWindSetting()
        : SubscribeAttribute("wind-setting")
    {
    }

    ~SubscribeAttributeFanControlWindSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWindSettingWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.WindSetting response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadFanControlGeneratedCommandList : public ReadAttribute {
public:
    ReadFanControlGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadFanControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeFanControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadFanControlAcceptedCommandList : public ReadAttribute {
public:
    ReadFanControlAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadFanControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeFanControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadFanControlAttributeList : public ReadAttribute {
public:
    ReadFanControlAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadFanControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeFanControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadFanControlFeatureMap : public ReadAttribute {
public:
    ReadFanControlFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadFanControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeFanControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadFanControlClusterRevision : public ReadAttribute {
public:
    ReadFanControlClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadFanControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeFanControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ThermostatUserInterfaceConfiguration                        | 0x0204 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * TemperatureDisplayMode                                            | 0x0000 |
| * KeypadLockout                                                     | 0x0001 |
| * ScheduleProgrammingVisibility                                     | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute TemperatureDisplayMode
 */
class ReadThermostatUserInterfaceConfigurationTemperatureDisplayMode : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationTemperatureDisplayMode()
        : ReadAttribute("temperature-display-mode")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationTemperatureDisplayMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        [cluster readAttributeTemperatureDisplayModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.TemperatureDisplayMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration TemperatureDisplayMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUserInterfaceConfigurationTemperatureDisplayMode : public WriteAttribute {
public:
    WriteThermostatUserInterfaceConfigurationTemperatureDisplayMode()
        : WriteAttribute("temperature-display-mode")
    {
        AddArgument("attr-name", "temperature-display-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUserInterfaceConfigurationTemperatureDisplayMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeTemperatureDisplayModeWithValue:value
                                                        params:params
                                             completionHandler:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError(
                                                         "ThermostatUserInterfaceConfiguration TemperatureDisplayMode write Error",
                                                         error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatUserInterfaceConfigurationTemperatureDisplayMode : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationTemperatureDisplayMode()
        : SubscribeAttribute("temperature-display-mode")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationTemperatureDisplayMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTemperatureDisplayModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.TemperatureDisplayMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute KeypadLockout
 */
class ReadThermostatUserInterfaceConfigurationKeypadLockout : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationKeypadLockout()
        : ReadAttribute("keypad-lockout")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationKeypadLockout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        [cluster readAttributeKeypadLockoutWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.KeypadLockout response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration KeypadLockout read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUserInterfaceConfigurationKeypadLockout : public WriteAttribute {
public:
    WriteThermostatUserInterfaceConfigurationKeypadLockout()
        : WriteAttribute("keypad-lockout")
    {
        AddArgument("attr-name", "keypad-lockout");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUserInterfaceConfigurationKeypadLockout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeKeypadLockoutWithValue:value
                                               params:params
                                    completionHandler:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("ThermostatUserInterfaceConfiguration KeypadLockout write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatUserInterfaceConfigurationKeypadLockout : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationKeypadLockout()
        : SubscribeAttribute("keypad-lockout")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationKeypadLockout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeKeypadLockoutWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.KeypadLockout response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ScheduleProgrammingVisibility
 */
class ReadThermostatUserInterfaceConfigurationScheduleProgrammingVisibility : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationScheduleProgrammingVisibility()
        : ReadAttribute("schedule-programming-visibility")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationScheduleProgrammingVisibility() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        [cluster readAttributeScheduleProgrammingVisibilityWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.ScheduleProgrammingVisibility response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration ScheduleProgrammingVisibility read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUserInterfaceConfigurationScheduleProgrammingVisibility : public WriteAttribute {
public:
    WriteThermostatUserInterfaceConfigurationScheduleProgrammingVisibility()
        : WriteAttribute("schedule-programming-visibility")
    {
        AddArgument("attr-name", "schedule-programming-visibility");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUserInterfaceConfigurationScheduleProgrammingVisibility() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) WriteAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeScheduleProgrammingVisibilityWithValue:value
                                                               params:params
                                                    completionHandler:^(NSError * _Nullable error) {
                                                        if (error != nil) {
                                                            LogNSError("ThermostatUserInterfaceConfiguration "
                                                                       "ScheduleProgrammingVisibility write Error",
                                                                error);
                                                        }
                                                        SetCommandExitStatus(error);
                                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatUserInterfaceConfigurationScheduleProgrammingVisibility : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationScheduleProgrammingVisibility()
        : SubscribeAttribute("schedule-programming-visibility")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationScheduleProgrammingVisibility() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeScheduleProgrammingVisibilityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.ScheduleProgrammingVisibility response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadThermostatUserInterfaceConfigurationGeneratedCommandList : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUserInterfaceConfigurationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadThermostatUserInterfaceConfigurationAcceptedCommandList : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUserInterfaceConfigurationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadThermostatUserInterfaceConfigurationAttributeList : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUserInterfaceConfigurationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadThermostatUserInterfaceConfigurationFeatureMap : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUserInterfaceConfigurationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadThermostatUserInterfaceConfigurationClusterRevision : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUserInterfaceConfigurationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                              endpoint:endpointId
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params: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 |
| * ColorTemperature                                                  | 0x0007 |
| * ColorMode                                                         | 0x0008 |
| * Options                                                           | 0x000F |
| * NumberOfPrimaries                                                 | 0x0010 |
| * Primary1X                                                         | 0x0011 |
| * Primary1Y                                                         | 0x0012 |
| * Primary1Intensity                                                 | 0x0013 |
| * Primary2X                                                         | 0x0015 |
| * Primary2Y                                                         | 0x0016 |
| * Primary2Intensity                                                 | 0x0017 |
| * Primary3X                                                         | 0x0019 |
| * Primary3Y                                                         | 0x001A |
| * Primary3Intensity                                                 | 0x001B |
| * Primary4X                                                         | 0x0020 |
| * Primary4Y                                                         | 0x0021 |
| * Primary4Intensity                                                 | 0x0022 |
| * Primary5X                                                         | 0x0024 |
| * Primary5Y                                                         | 0x0025 |
| * Primary5Intensity                                                 | 0x0026 |
| * Primary6X                                                         | 0x0028 |
| * Primary6Y                                                         | 0x0029 |
| * Primary6Intensity                                                 | 0x002A |
| * WhitePointX                                                       | 0x0030 |
| * WhitePointY                                                       | 0x0031 |
| * ColorPointRX                                                      | 0x0032 |
| * ColorPointRY                                                      | 0x0033 |
| * ColorPointRIntensity                                              | 0x0034 |
| * ColorPointGX                                                      | 0x0036 |
| * ColorPointGY                                                      | 0x0037 |
| * ColorPointGIntensity                                              | 0x0038 |
| * ColorPointBX                                                      | 0x003A |
| * ColorPointBY                                                      | 0x003B |
| * ColorPointBIntensity                                              | 0x003C |
| * EnhancedCurrentHue                                                | 0x4000 |
| * EnhancedColorMode                                                 | 0x4001 |
| * ColorLoopActive                                                   | 0x4002 |
| * ColorLoopDirection                                                | 0x4003 |
| * ColorLoopTime                                                     | 0x4004 |
| * ColorLoopStartEnhancedHue                                         | 0x4005 |
| * ColorLoopStoredEnhancedHue                                        | 0x4006 |
| * ColorCapabilities                                                 | 0x400A |
| * ColorTempPhysicalMinMireds                                        | 0x400B |
| * ColorTempPhysicalMaxMireds                                        | 0x400C |
| * CoupleColorTempToLevelMinMireds                                   | 0x400D |
| * StartUpColorTemperatureMireds                                     | 0x4010 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command MoveToHue
 */
class ColorControlMoveToHue : public ClusterCommand {
public:
    ColorControlMoveToHue()
        : ClusterCommand("move-to-hue")
    {
        AddArgument("Hue", 0, UINT8_MAX, &mRequest.hue);
        AddArgument("Direction", 0, UINT8_MAX, &mRequest.direction);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                       completionHandler:^(NSError * _Nullable error) {
                           responsesNeeded--;
                           if (error != nil) {
                               mError = error;
                               LogNSError("Error", error);
                           }
                           if (responsesNeeded == 0) {
                               SetCommandExitStatus(mError);
                           }
                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveToHue::Type mRequest;
};

/*
 * Command MoveHue
 */
class ColorControlMoveHue : public ClusterCommand {
public:
    ColorControlMoveHue()
        : ClusterCommand("move-hue")
    {
        AddArgument("MoveMode", 0, UINT8_MAX, &mRequest.moveMode);
        AddArgument("Rate", 0, UINT8_MAX, &mRequest.rate);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                     completionHandler:^(NSError * _Nullable error) {
                         responsesNeeded--;
                         if (error != nil) {
                             mError = error;
                             LogNSError("Error", error);
                         }
                         if (responsesNeeded == 0) {
                             SetCommandExitStatus(mError);
                         }
                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveHue::Type mRequest;
};

/*
 * Command StepHue
 */
class ColorControlStepHue : public ClusterCommand {
public:
    ColorControlStepHue()
        : ClusterCommand("step-hue")
    {
        AddArgument("StepMode", 0, UINT8_MAX, &mRequest.stepMode);
        AddArgument("StepSize", 0, UINT8_MAX, &mRequest.stepSize);
        AddArgument("TransitionTime", 0, UINT8_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                     completionHandler:^(NSError * _Nullable error) {
                         responsesNeeded--;
                         if (error != nil) {
                             mError = error;
                             LogNSError("Error", error);
                         }
                         if (responsesNeeded == 0) {
                             SetCommandExitStatus(mError);
                         }
                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::StepHue::Type mRequest;
};

/*
 * Command MoveToSaturation
 */
class ColorControlMoveToSaturation : public ClusterCommand {
public:
    ColorControlMoveToSaturation()
        : ClusterCommand("move-to-saturation")
    {
        AddArgument("Saturation", 0, UINT8_MAX, &mRequest.saturation);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                              completionHandler:^(NSError * _Nullable error) {
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveToSaturation::Type mRequest;
};

/*
 * Command MoveSaturation
 */
class ColorControlMoveSaturation : public ClusterCommand {
public:
    ColorControlMoveSaturation()
        : ClusterCommand("move-saturation")
    {
        AddArgument("MoveMode", 0, UINT8_MAX, &mRequest.moveMode);
        AddArgument("Rate", 0, UINT8_MAX, &mRequest.rate);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                            completionHandler:^(NSError * _Nullable error) {
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveSaturation::Type mRequest;
};

/*
 * Command StepSaturation
 */
class ColorControlStepSaturation : public ClusterCommand {
public:
    ColorControlStepSaturation()
        : ClusterCommand("step-saturation")
    {
        AddArgument("StepMode", 0, UINT8_MAX, &mRequest.stepMode);
        AddArgument("StepSize", 0, UINT8_MAX, &mRequest.stepSize);
        AddArgument("TransitionTime", 0, UINT8_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                            completionHandler:^(NSError * _Nullable error) {
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::StepSaturation::Type mRequest;
};

/*
 * Command MoveToHueAndSaturation
 */
class ColorControlMoveToHueAndSaturation : public ClusterCommand {
public:
    ColorControlMoveToHueAndSaturation()
        : ClusterCommand("move-to-hue-and-saturation")
    {
        AddArgument("Hue", 0, UINT8_MAX, &mRequest.hue);
        AddArgument("Saturation", 0, UINT8_MAX, &mRequest.saturation);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                                    completionHandler:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveToHueAndSaturation::Type mRequest;
};

/*
 * Command MoveToColor
 */
class ColorControlMoveToColor : public ClusterCommand {
public:
    ColorControlMoveToColor()
        : ClusterCommand("move-to-color")
    {
        AddArgument("ColorX", 0, UINT16_MAX, &mRequest.colorX);
        AddArgument("ColorY", 0, UINT16_MAX, &mRequest.colorY);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                         completionHandler:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveToColor::Type mRequest;
};

/*
 * Command MoveColor
 */
class ColorControlMoveColor : public ClusterCommand {
public:
    ColorControlMoveColor()
        : ClusterCommand("move-color")
    {
        AddArgument("RateX", INT16_MIN, INT16_MAX, &mRequest.rateX);
        AddArgument("RateY", INT16_MIN, INT16_MAX, &mRequest.rateY);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                       completionHandler:^(NSError * _Nullable error) {
                           responsesNeeded--;
                           if (error != nil) {
                               mError = error;
                               LogNSError("Error", error);
                           }
                           if (responsesNeeded == 0) {
                               SetCommandExitStatus(mError);
                           }
                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveColor::Type mRequest;
};

/*
 * Command StepColor
 */
class ColorControlStepColor : public ClusterCommand {
public:
    ColorControlStepColor()
        : ClusterCommand("step-color")
    {
        AddArgument("StepX", INT16_MIN, INT16_MAX, &mRequest.stepX);
        AddArgument("StepY", INT16_MIN, INT16_MAX, &mRequest.stepY);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                       completionHandler:^(NSError * _Nullable error) {
                           responsesNeeded--;
                           if (error != nil) {
                               mError = error;
                               LogNSError("Error", error);
                           }
                           if (responsesNeeded == 0) {
                               SetCommandExitStatus(mError);
                           }
                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::StepColor::Type mRequest;
};

/*
 * Command MoveToColorTemperature
 */
class ColorControlMoveToColorTemperature : public ClusterCommand {
public:
    ColorControlMoveToColorTemperature()
        : ClusterCommand("move-to-color-temperature")
    {
        AddArgument("ColorTemperature", 0, UINT16_MAX, &mRequest.colorTemperature);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterMoveToColorTemperatureParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.colorTemperature = [NSNumber numberWithUnsignedShort:mRequest.colorTemperature];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveToColorTemperatureWithParams:params
                                    completionHandler:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveToColorTemperature::Type mRequest;
};

/*
 * Command EnhancedMoveToHue
 */
class ColorControlEnhancedMoveToHue : public ClusterCommand {
public:
    ColorControlEnhancedMoveToHue()
        : ClusterCommand("enhanced-move-to-hue")
    {
        AddArgument("EnhancedHue", 0, UINT16_MAX, &mRequest.enhancedHue);
        AddArgument("Direction", 0, UINT8_MAX, &mRequest.direction);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000040) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                               completionHandler:^(NSError * _Nullable error) {
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::EnhancedMoveToHue::Type mRequest;
};

/*
 * Command EnhancedMoveHue
 */
class ColorControlEnhancedMoveHue : public ClusterCommand {
public:
    ColorControlEnhancedMoveHue()
        : ClusterCommand("enhanced-move-hue")
    {
        AddArgument("MoveMode", 0, UINT8_MAX, &mRequest.moveMode);
        AddArgument("Rate", 0, UINT16_MAX, &mRequest.rate);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000041) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                             completionHandler:^(NSError * _Nullable error) {
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::EnhancedMoveHue::Type mRequest;
};

/*
 * Command EnhancedStepHue
 */
class ColorControlEnhancedStepHue : public ClusterCommand {
public:
    ColorControlEnhancedStepHue()
        : ClusterCommand("enhanced-step-hue")
    {
        AddArgument("StepMode", 0, UINT8_MAX, &mRequest.stepMode);
        AddArgument("StepSize", 0, UINT16_MAX, &mRequest.stepSize);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000042) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                             completionHandler:^(NSError * _Nullable error) {
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::EnhancedStepHue::Type mRequest;
};

/*
 * Command EnhancedMoveToHueAndSaturation
 */
class ColorControlEnhancedMoveToHueAndSaturation : public ClusterCommand {
public:
    ColorControlEnhancedMoveToHueAndSaturation()
        : ClusterCommand("enhanced-move-to-hue-and-saturation")
    {
        AddArgument("EnhancedHue", 0, UINT16_MAX, &mRequest.enhancedHue);
        AddArgument("Saturation", 0, UINT8_MAX, &mRequest.saturation);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000043) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                                            completionHandler:^(NSError * _Nullable error) {
                                                responsesNeeded--;
                                                if (error != nil) {
                                                    mError = error;
                                                    LogNSError("Error", error);
                                                }
                                                if (responsesNeeded == 0) {
                                                    SetCommandExitStatus(mError);
                                                }
                                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::EnhancedMoveToHueAndSaturation::Type mRequest;
};

/*
 * Command ColorLoopSet
 */
class ColorControlColorLoopSet : public ClusterCommand {
public:
    ColorControlColorLoopSet()
        : ClusterCommand("color-loop-set")
    {
        AddArgument("UpdateFlags", 0, UINT8_MAX, &mRequest.updateFlags);
        AddArgument("Action", 0, UINT8_MAX, &mRequest.action);
        AddArgument("Direction", 0, UINT8_MAX, &mRequest.direction);
        AddArgument("Time", 0, UINT16_MAX, &mRequest.time);
        AddArgument("StartHue", 0, UINT16_MAX, &mRequest.startHue);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000044) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                          completionHandler:^(NSError * _Nullable error) {
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::ColorLoopSet::Type mRequest;
};

/*
 * Command StopMoveStep
 */
class ColorControlStopMoveStep : public ClusterCommand {
public:
    ColorControlStopMoveStep()
        : ClusterCommand("stop-move-step")
    {
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000047) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                          completionHandler:^(NSError * _Nullable error) {
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::StopMoveStep::Type mRequest;
};

/*
 * Command MoveColorTemperature
 */
class ColorControlMoveColorTemperature : public ClusterCommand {
public:
    ColorControlMoveColorTemperature()
        : ClusterCommand("move-color-temperature")
    {
        AddArgument("MoveMode", 0, UINT8_MAX, &mRequest.moveMode);
        AddArgument("Rate", 0, UINT16_MAX, &mRequest.rate);
        AddArgument("ColorTemperatureMinimumMireds", 0, UINT16_MAX, &mRequest.colorTemperatureMinimumMireds);
        AddArgument("ColorTemperatureMaximumMireds", 0, UINT16_MAX, &mRequest.colorTemperatureMaximumMireds);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x0000004B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                                  completionHandler:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveColorTemperature::Type mRequest;
};

/*
 * Command StepColorTemperature
 */
class ColorControlStepColorTemperature : public ClusterCommand {
public:
    ColorControlStepColorTemperature()
        : ClusterCommand("step-color-temperature")
    {
        AddArgument("StepMode", 0, UINT8_MAX, &mRequest.stepMode);
        AddArgument("StepSize", 0, UINT16_MAX, &mRequest.stepSize);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("ColorTemperatureMinimumMireds", 0, UINT16_MAX, &mRequest.colorTemperatureMinimumMireds);
        AddArgument("ColorTemperatureMaximumMireds", 0, UINT16_MAX, &mRequest.colorTemperatureMaximumMireds);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x0000004C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint: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
                                  completionHandler:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::StepColorTemperature::Type mRequest;
};

/*
 * Attribute CurrentHue
 */
class ReadColorControlCurrentHue : public ReadAttribute {
public:
    ReadColorControlCurrentHue()
        : ReadAttribute("current-hue")
    {
    }

    ~ReadColorControlCurrentHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeCurrentHueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CurrentHue response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CurrentHue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCurrentHue : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCurrentHue()
        : SubscribeAttribute("current-hue")
    {
    }

    ~SubscribeAttributeColorControlCurrentHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentHueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CurrentHue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentSaturation
 */
class ReadColorControlCurrentSaturation : public ReadAttribute {
public:
    ReadColorControlCurrentSaturation()
        : ReadAttribute("current-saturation")
    {
    }

    ~ReadColorControlCurrentSaturation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeCurrentSaturationWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CurrentSaturation response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CurrentSaturation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCurrentSaturation : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCurrentSaturation()
        : SubscribeAttribute("current-saturation")
    {
    }

    ~SubscribeAttributeColorControlCurrentSaturation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentSaturationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CurrentSaturation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RemainingTime
 */
class ReadColorControlRemainingTime : public ReadAttribute {
public:
    ReadColorControlRemainingTime()
        : ReadAttribute("remaining-time")
    {
    }

    ~ReadColorControlRemainingTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeRemainingTimeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.RemainingTime response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl RemainingTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlRemainingTime : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlRemainingTime()
        : SubscribeAttribute("remaining-time")
    {
    }

    ~SubscribeAttributeColorControlRemainingTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRemainingTimeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.RemainingTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentX
 */
class ReadColorControlCurrentX : public ReadAttribute {
public:
    ReadColorControlCurrentX()
        : ReadAttribute("current-x")
    {
    }

    ~ReadColorControlCurrentX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeCurrentXWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CurrentX response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CurrentX read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCurrentX : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCurrentX()
        : SubscribeAttribute("current-x")
    {
    }

    ~SubscribeAttributeColorControlCurrentX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentXWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CurrentX response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentY
 */
class ReadColorControlCurrentY : public ReadAttribute {
public:
    ReadColorControlCurrentY()
        : ReadAttribute("current-y")
    {
    }

    ~ReadColorControlCurrentY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeCurrentYWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CurrentY response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CurrentY read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCurrentY : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCurrentY()
        : SubscribeAttribute("current-y")
    {
    }

    ~SubscribeAttributeColorControlCurrentY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentYWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CurrentY response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DriftCompensation
 */
class ReadColorControlDriftCompensation : public ReadAttribute {
public:
    ReadColorControlDriftCompensation()
        : ReadAttribute("drift-compensation")
    {
    }

    ~ReadColorControlDriftCompensation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeDriftCompensationWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.DriftCompensation response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl DriftCompensation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlDriftCompensation : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlDriftCompensation()
        : SubscribeAttribute("drift-compensation")
    {
    }

    ~SubscribeAttributeColorControlDriftCompensation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDriftCompensationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.DriftCompensation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CompensationText
 */
class ReadColorControlCompensationText : public ReadAttribute {
public:
    ReadColorControlCompensationText()
        : ReadAttribute("compensation-text")
    {
    }

    ~ReadColorControlCompensationText() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeCompensationTextWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CompensationText response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CompensationText read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCompensationText : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCompensationText()
        : SubscribeAttribute("compensation-text")
    {
    }

    ~SubscribeAttributeColorControlCompensationText() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCompensationTextWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CompensationText response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorTemperature
 */
class ReadColorControlColorTemperature : public ReadAttribute {
public:
    ReadColorControlColorTemperature()
        : ReadAttribute("color-temperature")
    {
    }

    ~ReadColorControlColorTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorTemperatureWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorTemperature response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorTemperature read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorTemperature : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorTemperature()
        : SubscribeAttribute("color-temperature")
    {
    }

    ~SubscribeAttributeColorControlColorTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorTemperatureWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorTemperature response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorMode
 */
class ReadColorControlColorMode : public ReadAttribute {
public:
    ReadColorControlColorMode()
        : ReadAttribute("color-mode")
    {
    }

    ~ReadColorControlColorMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorMode : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorMode()
        : SubscribeAttribute("color-mode")
    {
    }

    ~SubscribeAttributeColorControlColorMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Options
 */
class ReadColorControlOptions : public ReadAttribute {
public:
    ReadColorControlOptions()
        : ReadAttribute("options")
    {
    }

    ~ReadColorControlOptions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeOptionsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Options response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Options read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlOptions : public WriteAttribute {
public:
    WriteColorControlOptions()
        : WriteAttribute("options")
    {
        AddArgument("attr-name", "options");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlOptions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOptionsWithValue:value
                                         params:params
                              completionHandler:^(NSError * _Nullable error) {
                                  if (error != nil) {
                                      LogNSError("ColorControl Options write Error", error);
                                  }
                                  SetCommandExitStatus(error);
                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeColorControlOptions : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlOptions()
        : SubscribeAttribute("options")
    {
    }

    ~SubscribeAttributeColorControlOptions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOptionsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Options response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfPrimaries
 */
class ReadColorControlNumberOfPrimaries : public ReadAttribute {
public:
    ReadColorControlNumberOfPrimaries()
        : ReadAttribute("number-of-primaries")
    {
    }

    ~ReadColorControlNumberOfPrimaries() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeNumberOfPrimariesWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.NumberOfPrimaries response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl NumberOfPrimaries read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlNumberOfPrimaries : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlNumberOfPrimaries()
        : SubscribeAttribute("number-of-primaries")
    {
    }

    ~SubscribeAttributeColorControlNumberOfPrimaries() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNumberOfPrimariesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.NumberOfPrimaries response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary1X
 */
class ReadColorControlPrimary1X : public ReadAttribute {
public:
    ReadColorControlPrimary1X()
        : ReadAttribute("primary1x")
    {
    }

    ~ReadColorControlPrimary1X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary1XWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary1X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary1X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary1X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary1X()
        : SubscribeAttribute("primary1x")
    {
    }

    ~SubscribeAttributeColorControlPrimary1X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary1XWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary1X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary1Y
 */
class ReadColorControlPrimary1Y : public ReadAttribute {
public:
    ReadColorControlPrimary1Y()
        : ReadAttribute("primary1y")
    {
    }

    ~ReadColorControlPrimary1Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary1YWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary1Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary1Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary1Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary1Y()
        : SubscribeAttribute("primary1y")
    {
    }

    ~SubscribeAttributeColorControlPrimary1Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary1YWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary1Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary1Intensity
 */
class ReadColorControlPrimary1Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary1Intensity()
        : ReadAttribute("primary1intensity")
    {
    }

    ~ReadColorControlPrimary1Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary1IntensityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary1Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary1Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary1Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary1Intensity()
        : SubscribeAttribute("primary1intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary1Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary1IntensityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary1Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary2X
 */
class ReadColorControlPrimary2X : public ReadAttribute {
public:
    ReadColorControlPrimary2X()
        : ReadAttribute("primary2x")
    {
    }

    ~ReadColorControlPrimary2X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary2XWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary2X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary2X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary2X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary2X()
        : SubscribeAttribute("primary2x")
    {
    }

    ~SubscribeAttributeColorControlPrimary2X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary2XWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary2X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary2Y
 */
class ReadColorControlPrimary2Y : public ReadAttribute {
public:
    ReadColorControlPrimary2Y()
        : ReadAttribute("primary2y")
    {
    }

    ~ReadColorControlPrimary2Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary2YWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary2Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary2Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary2Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary2Y()
        : SubscribeAttribute("primary2y")
    {
    }

    ~SubscribeAttributeColorControlPrimary2Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary2YWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary2Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary2Intensity
 */
class ReadColorControlPrimary2Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary2Intensity()
        : ReadAttribute("primary2intensity")
    {
    }

    ~ReadColorControlPrimary2Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary2IntensityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary2Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary2Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary2Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary2Intensity()
        : SubscribeAttribute("primary2intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary2Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary2IntensityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary2Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary3X
 */
class ReadColorControlPrimary3X : public ReadAttribute {
public:
    ReadColorControlPrimary3X()
        : ReadAttribute("primary3x")
    {
    }

    ~ReadColorControlPrimary3X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary3XWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary3X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary3X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary3X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary3X()
        : SubscribeAttribute("primary3x")
    {
    }

    ~SubscribeAttributeColorControlPrimary3X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary3XWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary3X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary3Y
 */
class ReadColorControlPrimary3Y : public ReadAttribute {
public:
    ReadColorControlPrimary3Y()
        : ReadAttribute("primary3y")
    {
    }

    ~ReadColorControlPrimary3Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary3YWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary3Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary3Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary3Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary3Y()
        : SubscribeAttribute("primary3y")
    {
    }

    ~SubscribeAttributeColorControlPrimary3Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary3YWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary3Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary3Intensity
 */
class ReadColorControlPrimary3Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary3Intensity()
        : ReadAttribute("primary3intensity")
    {
    }

    ~ReadColorControlPrimary3Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary3IntensityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary3Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary3Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary3Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary3Intensity()
        : SubscribeAttribute("primary3intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary3Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary3IntensityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary3Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary4X
 */
class ReadColorControlPrimary4X : public ReadAttribute {
public:
    ReadColorControlPrimary4X()
        : ReadAttribute("primary4x")
    {
    }

    ~ReadColorControlPrimary4X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary4XWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary4X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary4X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary4X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary4X()
        : SubscribeAttribute("primary4x")
    {
    }

    ~SubscribeAttributeColorControlPrimary4X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary4XWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary4X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary4Y
 */
class ReadColorControlPrimary4Y : public ReadAttribute {
public:
    ReadColorControlPrimary4Y()
        : ReadAttribute("primary4y")
    {
    }

    ~ReadColorControlPrimary4Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary4YWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary4Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary4Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary4Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary4Y()
        : SubscribeAttribute("primary4y")
    {
    }

    ~SubscribeAttributeColorControlPrimary4Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary4YWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary4Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary4Intensity
 */
class ReadColorControlPrimary4Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary4Intensity()
        : ReadAttribute("primary4intensity")
    {
    }

    ~ReadColorControlPrimary4Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary4IntensityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary4Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary4Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary4Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary4Intensity()
        : SubscribeAttribute("primary4intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary4Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary4IntensityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary4Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary5X
 */
class ReadColorControlPrimary5X : public ReadAttribute {
public:
    ReadColorControlPrimary5X()
        : ReadAttribute("primary5x")
    {
    }

    ~ReadColorControlPrimary5X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary5XWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary5X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary5X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary5X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary5X()
        : SubscribeAttribute("primary5x")
    {
    }

    ~SubscribeAttributeColorControlPrimary5X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary5XWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary5X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary5Y
 */
class ReadColorControlPrimary5Y : public ReadAttribute {
public:
    ReadColorControlPrimary5Y()
        : ReadAttribute("primary5y")
    {
    }

    ~ReadColorControlPrimary5Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary5YWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary5Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary5Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary5Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary5Y()
        : SubscribeAttribute("primary5y")
    {
    }

    ~SubscribeAttributeColorControlPrimary5Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary5YWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary5Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary5Intensity
 */
class ReadColorControlPrimary5Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary5Intensity()
        : ReadAttribute("primary5intensity")
    {
    }

    ~ReadColorControlPrimary5Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary5IntensityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary5Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary5Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary5Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary5Intensity()
        : SubscribeAttribute("primary5intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary5Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary5IntensityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary5Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary6X
 */
class ReadColorControlPrimary6X : public ReadAttribute {
public:
    ReadColorControlPrimary6X()
        : ReadAttribute("primary6x")
    {
    }

    ~ReadColorControlPrimary6X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000028) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary6XWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary6X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary6X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary6X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary6X()
        : SubscribeAttribute("primary6x")
    {
    }

    ~SubscribeAttributeColorControlPrimary6X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary6XWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary6X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary6Y
 */
class ReadColorControlPrimary6Y : public ReadAttribute {
public:
    ReadColorControlPrimary6Y()
        : ReadAttribute("primary6y")
    {
    }

    ~ReadColorControlPrimary6Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary6YWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary6Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary6Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary6Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary6Y()
        : SubscribeAttribute("primary6y")
    {
    }

    ~SubscribeAttributeColorControlPrimary6Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary6YWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary6Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary6Intensity
 */
class ReadColorControlPrimary6Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary6Intensity()
        : ReadAttribute("primary6intensity")
    {
    }

    ~ReadColorControlPrimary6Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000002A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary6IntensityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary6Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary6Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary6Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary6Intensity()
        : SubscribeAttribute("primary6intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary6Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePrimary6IntensityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary6Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WhitePointX
 */
class ReadColorControlWhitePointX : public ReadAttribute {
public:
    ReadColorControlWhitePointX()
        : ReadAttribute("white-point-x")
    {
    }

    ~ReadColorControlWhitePointX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeWhitePointXWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.WhitePointX response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl WhitePointX read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlWhitePointX : public WriteAttribute {
public:
    WriteColorControlWhitePointX()
        : WriteAttribute("white-point-x")
    {
        AddArgument("attr-name", "white-point-x");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlWhitePointX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeWhitePointXWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("ColorControl WhitePointX write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlWhitePointX : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlWhitePointX()
        : SubscribeAttribute("white-point-x")
    {
    }

    ~SubscribeAttributeColorControlWhitePointX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWhitePointXWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.WhitePointX response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WhitePointY
 */
class ReadColorControlWhitePointY : public ReadAttribute {
public:
    ReadColorControlWhitePointY()
        : ReadAttribute("white-point-y")
    {
    }

    ~ReadColorControlWhitePointY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeWhitePointYWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.WhitePointY response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl WhitePointY read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlWhitePointY : public WriteAttribute {
public:
    WriteColorControlWhitePointY()
        : WriteAttribute("white-point-y")
    {
        AddArgument("attr-name", "white-point-y");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlWhitePointY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeWhitePointYWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("ColorControl WhitePointY write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlWhitePointY : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlWhitePointY()
        : SubscribeAttribute("white-point-y")
    {
    }

    ~SubscribeAttributeColorControlWhitePointY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeWhitePointYWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.WhitePointY response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointRX
 */
class ReadColorControlColorPointRX : public ReadAttribute {
public:
    ReadColorControlColorPointRX()
        : ReadAttribute("color-point-rx")
    {
    }

    ~ReadColorControlColorPointRX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointRXWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointRX response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointRX read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointRX : public WriteAttribute {
public:
    WriteColorControlColorPointRX()
        : WriteAttribute("color-point-rx")
    {
        AddArgument("attr-name", "color-point-rx");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointRX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointRXWithValue:value
                                              params:params
                                   completionHandler:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("ColorControl ColorPointRX write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointRX : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointRX()
        : SubscribeAttribute("color-point-rx")
    {
    }

    ~SubscribeAttributeColorControlColorPointRX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorPointRXWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointRX response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointRY
 */
class ReadColorControlColorPointRY : public ReadAttribute {
public:
    ReadColorControlColorPointRY()
        : ReadAttribute("color-point-ry")
    {
    }

    ~ReadColorControlColorPointRY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000033) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointRYWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointRY response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointRY read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointRY : public WriteAttribute {
public:
    WriteColorControlColorPointRY()
        : WriteAttribute("color-point-ry")
    {
        AddArgument("attr-name", "color-point-ry");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointRY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointRYWithValue:value
                                              params:params
                                   completionHandler:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("ColorControl ColorPointRY write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointRY : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointRY()
        : SubscribeAttribute("color-point-ry")
    {
    }

    ~SubscribeAttributeColorControlColorPointRY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorPointRYWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointRY response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointRIntensity
 */
class ReadColorControlColorPointRIntensity : public ReadAttribute {
public:
    ReadColorControlColorPointRIntensity()
        : ReadAttribute("color-point-rintensity")
    {
    }

    ~ReadColorControlColorPointRIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000034) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointRIntensityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointRIntensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointRIntensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointRIntensity : public WriteAttribute {
public:
    WriteColorControlColorPointRIntensity()
        : WriteAttribute("color-point-rintensity")
    {
        AddArgument("attr-name", "color-point-rintensity");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointRIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeColorPointRIntensityWithValue:value
                                                      params:params
                                           completionHandler:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("ColorControl ColorPointRIntensity write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeColorControlColorPointRIntensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointRIntensity()
        : SubscribeAttribute("color-point-rintensity")
    {
    }

    ~SubscribeAttributeColorControlColorPointRIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorPointRIntensityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointRIntensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointGX
 */
class ReadColorControlColorPointGX : public ReadAttribute {
public:
    ReadColorControlColorPointGX()
        : ReadAttribute("color-point-gx")
    {
    }

    ~ReadColorControlColorPointGX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000036) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointGXWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointGX response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointGX read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointGX : public WriteAttribute {
public:
    WriteColorControlColorPointGX()
        : WriteAttribute("color-point-gx")
    {
        AddArgument("attr-name", "color-point-gx");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointGX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000036) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointGXWithValue:value
                                              params:params
                                   completionHandler:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("ColorControl ColorPointGX write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointGX : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointGX()
        : SubscribeAttribute("color-point-gx")
    {
    }

    ~SubscribeAttributeColorControlColorPointGX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000036) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorPointGXWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointGX response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointGY
 */
class ReadColorControlColorPointGY : public ReadAttribute {
public:
    ReadColorControlColorPointGY()
        : ReadAttribute("color-point-gy")
    {
    }

    ~ReadColorControlColorPointGY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000037) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointGYWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointGY response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointGY read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointGY : public WriteAttribute {
public:
    WriteColorControlColorPointGY()
        : WriteAttribute("color-point-gy")
    {
        AddArgument("attr-name", "color-point-gy");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointGY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000037) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointGYWithValue:value
                                              params:params
                                   completionHandler:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("ColorControl ColorPointGY write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointGY : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointGY()
        : SubscribeAttribute("color-point-gy")
    {
    }

    ~SubscribeAttributeColorControlColorPointGY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000037) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorPointGYWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointGY response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointGIntensity
 */
class ReadColorControlColorPointGIntensity : public ReadAttribute {
public:
    ReadColorControlColorPointGIntensity()
        : ReadAttribute("color-point-gintensity")
    {
    }

    ~ReadColorControlColorPointGIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000038) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointGIntensityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointGIntensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointGIntensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointGIntensity : public WriteAttribute {
public:
    WriteColorControlColorPointGIntensity()
        : WriteAttribute("color-point-gintensity")
    {
        AddArgument("attr-name", "color-point-gintensity");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointGIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000038) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeColorPointGIntensityWithValue:value
                                                      params:params
                                           completionHandler:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("ColorControl ColorPointGIntensity write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeColorControlColorPointGIntensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointGIntensity()
        : SubscribeAttribute("color-point-gintensity")
    {
    }

    ~SubscribeAttributeColorControlColorPointGIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000038) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorPointGIntensityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointGIntensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointBX
 */
class ReadColorControlColorPointBX : public ReadAttribute {
public:
    ReadColorControlColorPointBX()
        : ReadAttribute("color-point-bx")
    {
    }

    ~ReadColorControlColorPointBX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000003A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointBXWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointBX response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointBX read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointBX : public WriteAttribute {
public:
    WriteColorControlColorPointBX()
        : WriteAttribute("color-point-bx")
    {
        AddArgument("attr-name", "color-point-bx");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointBX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x0000003A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointBXWithValue:value
                                              params:params
                                   completionHandler:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("ColorControl ColorPointBX write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointBX : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointBX()
        : SubscribeAttribute("color-point-bx")
    {
    }

    ~SubscribeAttributeColorControlColorPointBX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000003A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorPointBXWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointBX response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointBY
 */
class ReadColorControlColorPointBY : public ReadAttribute {
public:
    ReadColorControlColorPointBY()
        : ReadAttribute("color-point-by")
    {
    }

    ~ReadColorControlColorPointBY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000003B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointBYWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointBY response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointBY read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointBY : public WriteAttribute {
public:
    WriteColorControlColorPointBY()
        : WriteAttribute("color-point-by")
    {
        AddArgument("attr-name", "color-point-by");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointBY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x0000003B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointBYWithValue:value
                                              params:params
                                   completionHandler:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("ColorControl ColorPointBY write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointBY : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointBY()
        : SubscribeAttribute("color-point-by")
    {
    }

    ~SubscribeAttributeColorControlColorPointBY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000003B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorPointBYWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointBY response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointBIntensity
 */
class ReadColorControlColorPointBIntensity : public ReadAttribute {
public:
    ReadColorControlColorPointBIntensity()
        : ReadAttribute("color-point-bintensity")
    {
    }

    ~ReadColorControlColorPointBIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000003C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointBIntensityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointBIntensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointBIntensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointBIntensity : public WriteAttribute {
public:
    WriteColorControlColorPointBIntensity()
        : WriteAttribute("color-point-bintensity")
    {
        AddArgument("attr-name", "color-point-bintensity");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointBIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x0000003C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeColorPointBIntensityWithValue:value
                                                      params:params
                                           completionHandler:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("ColorControl ColorPointBIntensity write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeColorControlColorPointBIntensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointBIntensity()
        : SubscribeAttribute("color-point-bintensity")
    {
    }

    ~SubscribeAttributeColorControlColorPointBIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000003C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorPointBIntensityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointBIntensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnhancedCurrentHue
 */
class ReadColorControlEnhancedCurrentHue : public ReadAttribute {
public:
    ReadColorControlEnhancedCurrentHue()
        : ReadAttribute("enhanced-current-hue")
    {
    }

    ~ReadColorControlEnhancedCurrentHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeEnhancedCurrentHueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.EnhancedCurrentHue response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl EnhancedCurrentHue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlEnhancedCurrentHue : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlEnhancedCurrentHue()
        : SubscribeAttribute("enhanced-current-hue")
    {
    }

    ~SubscribeAttributeColorControlEnhancedCurrentHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEnhancedCurrentHueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.EnhancedCurrentHue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnhancedColorMode
 */
class ReadColorControlEnhancedColorMode : public ReadAttribute {
public:
    ReadColorControlEnhancedColorMode()
        : ReadAttribute("enhanced-color-mode")
    {
    }

    ~ReadColorControlEnhancedColorMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeEnhancedColorModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.EnhancedColorMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl EnhancedColorMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlEnhancedColorMode : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlEnhancedColorMode()
        : SubscribeAttribute("enhanced-color-mode")
    {
    }

    ~SubscribeAttributeColorControlEnhancedColorMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEnhancedColorModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.EnhancedColorMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorLoopActive
 */
class ReadColorControlColorLoopActive : public ReadAttribute {
public:
    ReadColorControlColorLoopActive()
        : ReadAttribute("color-loop-active")
    {
    }

    ~ReadColorControlColorLoopActive() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorLoopActiveWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorLoopActive response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorLoopActive read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorLoopActive : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorLoopActive()
        : SubscribeAttribute("color-loop-active")
    {
    }

    ~SubscribeAttributeColorControlColorLoopActive() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorLoopActiveWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopActive response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorLoopDirection
 */
class ReadColorControlColorLoopDirection : public ReadAttribute {
public:
    ReadColorControlColorLoopDirection()
        : ReadAttribute("color-loop-direction")
    {
    }

    ~ReadColorControlColorLoopDirection() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorLoopDirectionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorLoopDirection response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorLoopDirection read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorLoopDirection : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorLoopDirection()
        : SubscribeAttribute("color-loop-direction")
    {
    }

    ~SubscribeAttributeColorControlColorLoopDirection() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorLoopDirectionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopDirection response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorLoopTime
 */
class ReadColorControlColorLoopTime : public ReadAttribute {
public:
    ReadColorControlColorLoopTime()
        : ReadAttribute("color-loop-time")
    {
    }

    ~ReadColorControlColorLoopTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorLoopTimeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorLoopTime response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorLoopTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorLoopTime : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorLoopTime()
        : SubscribeAttribute("color-loop-time")
    {
    }

    ~SubscribeAttributeColorControlColorLoopTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorLoopTimeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorLoopStartEnhancedHue
 */
class ReadColorControlColorLoopStartEnhancedHue : public ReadAttribute {
public:
    ReadColorControlColorLoopStartEnhancedHue()
        : ReadAttribute("color-loop-start-enhanced-hue")
    {
    }

    ~ReadColorControlColorLoopStartEnhancedHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster
            readAttributeColorLoopStartEnhancedHueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopStartEnhancedHue response %@", [value description]);
                if (error != nil) {
                    LogNSError("ColorControl ColorLoopStartEnhancedHue read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorLoopStartEnhancedHue : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorLoopStartEnhancedHue()
        : SubscribeAttribute("color-loop-start-enhanced-hue")
    {
    }

    ~SubscribeAttributeColorControlColorLoopStartEnhancedHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorLoopStartEnhancedHueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopStartEnhancedHue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorLoopStoredEnhancedHue
 */
class ReadColorControlColorLoopStoredEnhancedHue : public ReadAttribute {
public:
    ReadColorControlColorLoopStoredEnhancedHue()
        : ReadAttribute("color-loop-stored-enhanced-hue")
    {
    }

    ~ReadColorControlColorLoopStoredEnhancedHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster
            readAttributeColorLoopStoredEnhancedHueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopStoredEnhancedHue response %@", [value description]);
                if (error != nil) {
                    LogNSError("ColorControl ColorLoopStoredEnhancedHue read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorLoopStoredEnhancedHue : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorLoopStoredEnhancedHue()
        : SubscribeAttribute("color-loop-stored-enhanced-hue")
    {
    }

    ~SubscribeAttributeColorControlColorLoopStoredEnhancedHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorLoopStoredEnhancedHueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopStoredEnhancedHue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorCapabilities
 */
class ReadColorControlColorCapabilities : public ReadAttribute {
public:
    ReadColorControlColorCapabilities()
        : ReadAttribute("color-capabilities")
    {
    }

    ~ReadColorControlColorCapabilities() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000400A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorCapabilitiesWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorCapabilities response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorCapabilities read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorCapabilities : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorCapabilities()
        : SubscribeAttribute("color-capabilities")
    {
    }

    ~SubscribeAttributeColorControlColorCapabilities() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000400A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorCapabilitiesWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorCapabilities response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorTempPhysicalMinMireds
 */
class ReadColorControlColorTempPhysicalMinMireds : public ReadAttribute {
public:
    ReadColorControlColorTempPhysicalMinMireds()
        : ReadAttribute("color-temp-physical-min-mireds")
    {
    }

    ~ReadColorControlColorTempPhysicalMinMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000400B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster
            readAttributeColorTempPhysicalMinMiredsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorTempPhysicalMinMireds response %@", [value description]);
                if (error != nil) {
                    LogNSError("ColorControl ColorTempPhysicalMinMireds read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorTempPhysicalMinMireds : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorTempPhysicalMinMireds()
        : SubscribeAttribute("color-temp-physical-min-mireds")
    {
    }

    ~SubscribeAttributeColorControlColorTempPhysicalMinMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000400B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorTempPhysicalMinMiredsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorTempPhysicalMinMireds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorTempPhysicalMaxMireds
 */
class ReadColorControlColorTempPhysicalMaxMireds : public ReadAttribute {
public:
    ReadColorControlColorTempPhysicalMaxMireds()
        : ReadAttribute("color-temp-physical-max-mireds")
    {
    }

    ~ReadColorControlColorTempPhysicalMaxMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000400C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster
            readAttributeColorTempPhysicalMaxMiredsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorTempPhysicalMaxMireds response %@", [value description]);
                if (error != nil) {
                    LogNSError("ColorControl ColorTempPhysicalMaxMireds read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorTempPhysicalMaxMireds : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorTempPhysicalMaxMireds()
        : SubscribeAttribute("color-temp-physical-max-mireds")
    {
    }

    ~SubscribeAttributeColorControlColorTempPhysicalMaxMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000400C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeColorTempPhysicalMaxMiredsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorTempPhysicalMaxMireds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CoupleColorTempToLevelMinMireds
 */
class ReadColorControlCoupleColorTempToLevelMinMireds : public ReadAttribute {
public:
    ReadColorControlCoupleColorTempToLevelMinMireds()
        : ReadAttribute("couple-color-temp-to-level-min-mireds")
    {
    }

    ~ReadColorControlCoupleColorTempToLevelMinMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000400D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeCoupleColorTempToLevelMinMiredsWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CoupleColorTempToLevelMinMireds response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CoupleColorTempToLevelMinMireds read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCoupleColorTempToLevelMinMireds : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCoupleColorTempToLevelMinMireds()
        : SubscribeAttribute("couple-color-temp-to-level-min-mireds")
    {
    }

    ~SubscribeAttributeColorControlCoupleColorTempToLevelMinMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000400D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCoupleColorTempToLevelMinMiredsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CoupleColorTempToLevelMinMireds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StartUpColorTemperatureMireds
 */
class ReadColorControlStartUpColorTemperatureMireds : public ReadAttribute {
public:
    ReadColorControlStartUpColorTemperatureMireds()
        : ReadAttribute("start-up-color-temperature-mireds")
    {
    }

    ~ReadColorControlStartUpColorTemperatureMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeStartUpColorTemperatureMiredsWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.StartUpColorTemperatureMireds response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl StartUpColorTemperatureMireds read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlStartUpColorTemperatureMireds : public WriteAttribute {
public:
    WriteColorControlStartUpColorTemperatureMireds()
        : WriteAttribute("start-up-color-temperature-mireds")
    {
        AddArgument("attr-name", "start-up-color-temperature-mireds");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlStartUpColorTemperatureMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00004010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeStartUpColorTemperatureMiredsWithValue:value
                                                          params:params
                                               completionHandler:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("ColorControl StartUpColorTemperatureMireds write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlStartUpColorTemperatureMireds : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlStartUpColorTemperatureMireds()
        : SubscribeAttribute("start-up-color-temperature-mireds")
    {
    }

    ~SubscribeAttributeColorControlStartUpColorTemperatureMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeStartUpColorTemperatureMiredsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.StartUpColorTemperatureMireds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadColorControlGeneratedCommandList : public ReadAttribute {
public:
    ReadColorControlGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadColorControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeColorControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadColorControlAcceptedCommandList : public ReadAttribute {
public:
    ReadColorControlAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadColorControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeColorControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadColorControlAttributeList : public ReadAttribute {
public:
    ReadColorControlAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadColorControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeColorControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadColorControlFeatureMap : public ReadAttribute {
public:
    ReadColorControlFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadColorControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeColorControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadColorControlClusterRevision : public ReadAttribute {
public:
    ReadColorControlClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadColorControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeColorControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster BallastConfiguration                                        | 0x0301 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * PhysicalMinLevel                                                  | 0x0000 |
| * PhysicalMaxLevel                                                  | 0x0001 |
| * BallastStatus                                                     | 0x0002 |
| * MinLevel                                                          | 0x0010 |
| * MaxLevel                                                          | 0x0011 |
| * IntrinsicBalanceFactor                                            | 0x0014 |
| * BallastFactorAdjustment                                           | 0x0015 |
| * LampQuantity                                                      | 0x0020 |
| * LampType                                                          | 0x0030 |
| * LampManufacturer                                                  | 0x0031 |
| * LampRatedHours                                                    | 0x0032 |
| * LampBurnHours                                                     | 0x0033 |
| * LampAlarmMode                                                     | 0x0034 |
| * LampBurnHoursTripPoint                                            | 0x0035 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute PhysicalMinLevel
 */
class ReadBallastConfigurationPhysicalMinLevel : public ReadAttribute {
public:
    ReadBallastConfigurationPhysicalMinLevel()
        : ReadAttribute("physical-min-level")
    {
    }

    ~ReadBallastConfigurationPhysicalMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributePhysicalMinLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.PhysicalMinLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration PhysicalMinLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationPhysicalMinLevel : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationPhysicalMinLevel()
        : SubscribeAttribute("physical-min-level")
    {
    }

    ~SubscribeAttributeBallastConfigurationPhysicalMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePhysicalMinLevelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.PhysicalMinLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalMaxLevel
 */
class ReadBallastConfigurationPhysicalMaxLevel : public ReadAttribute {
public:
    ReadBallastConfigurationPhysicalMaxLevel()
        : ReadAttribute("physical-max-level")
    {
    }

    ~ReadBallastConfigurationPhysicalMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributePhysicalMaxLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.PhysicalMaxLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration PhysicalMaxLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationPhysicalMaxLevel : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationPhysicalMaxLevel()
        : SubscribeAttribute("physical-max-level")
    {
    }

    ~SubscribeAttributeBallastConfigurationPhysicalMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePhysicalMaxLevelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.PhysicalMaxLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BallastStatus
 */
class ReadBallastConfigurationBallastStatus : public ReadAttribute {
public:
    ReadBallastConfigurationBallastStatus()
        : ReadAttribute("ballast-status")
    {
    }

    ~ReadBallastConfigurationBallastStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeBallastStatusWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.BallastStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration BallastStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationBallastStatus : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationBallastStatus()
        : SubscribeAttribute("ballast-status")
    {
    }

    ~SubscribeAttributeBallastConfigurationBallastStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBallastStatusWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.BallastStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinLevel
 */
class ReadBallastConfigurationMinLevel : public ReadAttribute {
public:
    ReadBallastConfigurationMinLevel()
        : ReadAttribute("min-level")
    {
    }

    ~ReadBallastConfigurationMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeMinLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.MinLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration MinLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationMinLevel : public WriteAttribute {
public:
    WriteBallastConfigurationMinLevel()
        : WriteAttribute("min-level")
    {
        AddArgument("attr-name", "min-level");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeMinLevelWithValue:value
                                          params:params
                               completionHandler:^(NSError * _Nullable error) {
                                   if (error != nil) {
                                       LogNSError("BallastConfiguration MinLevel write Error", error);
                                   }
                                   SetCommandExitStatus(error);
                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationMinLevel : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationMinLevel()
        : SubscribeAttribute("min-level")
    {
    }

    ~SubscribeAttributeBallastConfigurationMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinLevelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.MinLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxLevel
 */
class ReadBallastConfigurationMaxLevel : public ReadAttribute {
public:
    ReadBallastConfigurationMaxLevel()
        : ReadAttribute("max-level")
    {
    }

    ~ReadBallastConfigurationMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeMaxLevelWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.MaxLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration MaxLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationMaxLevel : public WriteAttribute {
public:
    WriteBallastConfigurationMaxLevel()
        : WriteAttribute("max-level")
    {
        AddArgument("attr-name", "max-level");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeMaxLevelWithValue:value
                                          params:params
                               completionHandler:^(NSError * _Nullable error) {
                                   if (error != nil) {
                                       LogNSError("BallastConfiguration MaxLevel write Error", error);
                                   }
                                   SetCommandExitStatus(error);
                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationMaxLevel : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationMaxLevel()
        : SubscribeAttribute("max-level")
    {
    }

    ~SubscribeAttributeBallastConfigurationMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxLevelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.MaxLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute IntrinsicBalanceFactor
 */
class ReadBallastConfigurationIntrinsicBalanceFactor : public ReadAttribute {
public:
    ReadBallastConfigurationIntrinsicBalanceFactor()
        : ReadAttribute("intrinsic-balance-factor")
    {
    }

    ~ReadBallastConfigurationIntrinsicBalanceFactor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeIntrinsicBalanceFactorWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.IntrinsicBalanceFactor response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration IntrinsicBalanceFactor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationIntrinsicBalanceFactor : public WriteAttribute {
public:
    WriteBallastConfigurationIntrinsicBalanceFactor()
        : WriteAttribute("intrinsic-balance-factor")
    {
        AddArgument("attr-name", "intrinsic-balance-factor");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationIntrinsicBalanceFactor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeIntrinsicBalanceFactorWithValue:value
                                                        params:params
                                             completionHandler:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("BallastConfiguration IntrinsicBalanceFactor write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationIntrinsicBalanceFactor : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationIntrinsicBalanceFactor()
        : SubscribeAttribute("intrinsic-balance-factor")
    {
    }

    ~SubscribeAttributeBallastConfigurationIntrinsicBalanceFactor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeIntrinsicBalanceFactorWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.IntrinsicBalanceFactor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BallastFactorAdjustment
 */
class ReadBallastConfigurationBallastFactorAdjustment : public ReadAttribute {
public:
    ReadBallastConfigurationBallastFactorAdjustment()
        : ReadAttribute("ballast-factor-adjustment")
    {
    }

    ~ReadBallastConfigurationBallastFactorAdjustment() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster
            readAttributeBallastFactorAdjustmentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.BallastFactorAdjustment response %@", [value description]);
                if (error != nil) {
                    LogNSError("BallastConfiguration BallastFactorAdjustment read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationBallastFactorAdjustment : public WriteAttribute {
public:
    WriteBallastConfigurationBallastFactorAdjustment()
        : WriteAttribute("ballast-factor-adjustment")
    {
        AddArgument("attr-name", "ballast-factor-adjustment");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationBallastFactorAdjustment() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeBallastFactorAdjustmentWithValue:value
                                                         params:params
                                              completionHandler:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("BallastConfiguration BallastFactorAdjustment write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationBallastFactorAdjustment : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationBallastFactorAdjustment()
        : SubscribeAttribute("ballast-factor-adjustment")
    {
    }

    ~SubscribeAttributeBallastConfigurationBallastFactorAdjustment() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBallastFactorAdjustmentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.BallastFactorAdjustment response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampQuantity
 */
class ReadBallastConfigurationLampQuantity : public ReadAttribute {
public:
    ReadBallastConfigurationLampQuantity()
        : ReadAttribute("lamp-quantity")
    {
    }

    ~ReadBallastConfigurationLampQuantity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampQuantityWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampQuantity response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampQuantity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationLampQuantity : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampQuantity()
        : SubscribeAttribute("lamp-quantity")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampQuantity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLampQuantityWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampQuantity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampType
 */
class ReadBallastConfigurationLampType : public ReadAttribute {
public:
    ReadBallastConfigurationLampType()
        : ReadAttribute("lamp-type")
    {
    }

    ~ReadBallastConfigurationLampType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampTypeWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampType response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampType : public WriteAttribute {
public:
    WriteBallastConfigurationLampType()
        : WriteAttribute("lamp-type")
    {
        AddArgument("attr-name", "lamp-type");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeLampTypeWithValue:value
                                          params:params
                               completionHandler:^(NSError * _Nullable error) {
                                   if (error != nil) {
                                       LogNSError("BallastConfiguration LampType write Error", error);
                                   }
                                   SetCommandExitStatus(error);
                               }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBallastConfigurationLampType : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampType()
        : SubscribeAttribute("lamp-type")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLampTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampManufacturer
 */
class ReadBallastConfigurationLampManufacturer : public ReadAttribute {
public:
    ReadBallastConfigurationLampManufacturer()
        : ReadAttribute("lamp-manufacturer")
    {
    }

    ~ReadBallastConfigurationLampManufacturer() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampManufacturerWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampManufacturer response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampManufacturer read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampManufacturer : public WriteAttribute {
public:
    WriteBallastConfigurationLampManufacturer()
        : WriteAttribute("lamp-manufacturer")
    {
        AddArgument("attr-name", "lamp-manufacturer");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampManufacturer() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeLampManufacturerWithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("BallastConfiguration LampManufacturer write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBallastConfigurationLampManufacturer : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampManufacturer()
        : SubscribeAttribute("lamp-manufacturer")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampManufacturer() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLampManufacturerWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampManufacturer response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampRatedHours
 */
class ReadBallastConfigurationLampRatedHours : public ReadAttribute {
public:
    ReadBallastConfigurationLampRatedHours()
        : ReadAttribute("lamp-rated-hours")
    {
    }

    ~ReadBallastConfigurationLampRatedHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampRatedHoursWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampRatedHours response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampRatedHours read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampRatedHours : public WriteAttribute {
public:
    WriteBallastConfigurationLampRatedHours()
        : WriteAttribute("lamp-rated-hours")
    {
        AddArgument("attr-name", "lamp-rated-hours");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampRatedHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeLampRatedHoursWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("BallastConfiguration LampRatedHours write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeBallastConfigurationLampRatedHours : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampRatedHours()
        : SubscribeAttribute("lamp-rated-hours")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampRatedHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLampRatedHoursWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampRatedHours response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampBurnHours
 */
class ReadBallastConfigurationLampBurnHours : public ReadAttribute {
public:
    ReadBallastConfigurationLampBurnHours()
        : ReadAttribute("lamp-burn-hours")
    {
    }

    ~ReadBallastConfigurationLampBurnHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000033) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampBurnHoursWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampBurnHours response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampBurnHours read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampBurnHours : public WriteAttribute {
public:
    WriteBallastConfigurationLampBurnHours()
        : WriteAttribute("lamp-burn-hours")
    {
        AddArgument("attr-name", "lamp-burn-hours");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampBurnHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeLampBurnHoursWithValue:value
                                               params:params
                                    completionHandler:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("BallastConfiguration LampBurnHours write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeBallastConfigurationLampBurnHours : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampBurnHours()
        : SubscribeAttribute("lamp-burn-hours")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampBurnHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLampBurnHoursWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampBurnHours response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampAlarmMode
 */
class ReadBallastConfigurationLampAlarmMode : public ReadAttribute {
public:
    ReadBallastConfigurationLampAlarmMode()
        : ReadAttribute("lamp-alarm-mode")
    {
    }

    ~ReadBallastConfigurationLampAlarmMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000034) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampAlarmModeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampAlarmMode response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampAlarmMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampAlarmMode : public WriteAttribute {
public:
    WriteBallastConfigurationLampAlarmMode()
        : WriteAttribute("lamp-alarm-mode")
    {
        AddArgument("attr-name", "lamp-alarm-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampAlarmMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeLampAlarmModeWithValue:value
                                               params:params
                                    completionHandler:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("BallastConfiguration LampAlarmMode write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationLampAlarmMode : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampAlarmMode()
        : SubscribeAttribute("lamp-alarm-mode")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampAlarmMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLampAlarmModeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampAlarmMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampBurnHoursTripPoint
 */
class ReadBallastConfigurationLampBurnHoursTripPoint : public ReadAttribute {
public:
    ReadBallastConfigurationLampBurnHoursTripPoint()
        : ReadAttribute("lamp-burn-hours-trip-point")
    {
    }

    ~ReadBallastConfigurationLampBurnHoursTripPoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000035) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampBurnHoursTripPointWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampBurnHoursTripPoint response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampBurnHoursTripPoint read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampBurnHoursTripPoint : public WriteAttribute {
public:
    WriteBallastConfigurationLampBurnHoursTripPoint()
        : WriteAttribute("lamp-burn-hours-trip-point")
    {
        AddArgument("attr-name", "lamp-burn-hours-trip-point");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampBurnHoursTripPoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeLampBurnHoursTripPointWithValue:value
                                                        params:params
                                             completionHandler:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("BallastConfiguration LampBurnHoursTripPoint write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeBallastConfigurationLampBurnHoursTripPoint : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampBurnHoursTripPoint()
        : SubscribeAttribute("lamp-burn-hours-trip-point")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampBurnHoursTripPoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLampBurnHoursTripPointWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampBurnHoursTripPoint response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBallastConfigurationGeneratedCommandList : public ReadAttribute {
public:
    ReadBallastConfigurationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBallastConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBallastConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBallastConfigurationAcceptedCommandList : public ReadAttribute {
public:
    ReadBallastConfigurationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBallastConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBallastConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBallastConfigurationAttributeList : public ReadAttribute {
public:
    ReadBallastConfigurationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBallastConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBallastConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBallastConfigurationFeatureMap : public ReadAttribute {
public:
    ReadBallastConfigurationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBallastConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBallastConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBallastConfigurationClusterRevision : public ReadAttribute {
public:
    ReadBallastConfigurationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBallastConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBallastConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                         endpoint:endpointId
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster IlluminanceMeasurement                                      | 0x0400 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasuredValue                                                     | 0x0000 |
| * MinMeasuredValue                                                  | 0x0001 |
| * MaxMeasuredValue                                                  | 0x0002 |
| * Tolerance                                                         | 0x0003 |
| * LightSensorType                                                   | 0x0004 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MeasuredValue
 */
class ReadIlluminanceMeasurementMeasuredValue : public ReadAttribute {
public:
    ReadIlluminanceMeasurementMeasuredValue()
        : ReadAttribute("measured-value")
    {
    }

    ~ReadIlluminanceMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.MeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement MeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementMeasuredValue()
        : SubscribeAttribute("measured-value")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.MeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinMeasuredValue
 */
class ReadIlluminanceMeasurementMinMeasuredValue : public ReadAttribute {
public:
    ReadIlluminanceMeasurementMinMeasuredValue()
        : ReadAttribute("min-measured-value")
    {
    }

    ~ReadIlluminanceMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMinMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.MinMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement MinMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementMinMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementMinMeasuredValue()
        : SubscribeAttribute("min-measured-value")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.MinMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxMeasuredValue
 */
class ReadIlluminanceMeasurementMaxMeasuredValue : public ReadAttribute {
public:
    ReadIlluminanceMeasurementMaxMeasuredValue()
        : ReadAttribute("max-measured-value")
    {
    }

    ~ReadIlluminanceMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.MaxMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement MaxMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementMaxMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementMaxMeasuredValue()
        : SubscribeAttribute("max-measured-value")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.MaxMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Tolerance
 */
class ReadIlluminanceMeasurementTolerance : public ReadAttribute {
public:
    ReadIlluminanceMeasurementTolerance()
        : ReadAttribute("tolerance")
    {
    }

    ~ReadIlluminanceMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeToleranceWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.Tolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement Tolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementTolerance : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementTolerance()
        : SubscribeAttribute("tolerance")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeToleranceWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.Tolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LightSensorType
 */
class ReadIlluminanceMeasurementLightSensorType : public ReadAttribute {
public:
    ReadIlluminanceMeasurementLightSensorType()
        : ReadAttribute("light-sensor-type")
    {
    }

    ~ReadIlluminanceMeasurementLightSensorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeLightSensorTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.LightSensorType response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement LightSensorType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementLightSensorType : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementLightSensorType()
        : SubscribeAttribute("light-sensor-type")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementLightSensorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLightSensorTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.LightSensorType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadIlluminanceMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadIlluminanceMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadIlluminanceMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadIlluminanceMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadIlluminanceMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadIlluminanceMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadIlluminanceMeasurementAttributeList : public ReadAttribute {
public:
    ReadIlluminanceMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadIlluminanceMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadIlluminanceMeasurementFeatureMap : public ReadAttribute {
public:
    ReadIlluminanceMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadIlluminanceMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadIlluminanceMeasurementClusterRevision : public ReadAttribute {
public:
    ReadIlluminanceMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadIlluminanceMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster TemperatureMeasurement                                      | 0x0402 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasuredValue                                                     | 0x0000 |
| * MinMeasuredValue                                                  | 0x0001 |
| * MaxMeasuredValue                                                  | 0x0002 |
| * Tolerance                                                         | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MeasuredValue
 */
class ReadTemperatureMeasurementMeasuredValue : public ReadAttribute {
public:
    ReadTemperatureMeasurementMeasuredValue()
        : ReadAttribute("measured-value")
    {
    }

    ~ReadTemperatureMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.MeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement MeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementMeasuredValue()
        : SubscribeAttribute("measured-value")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.MeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinMeasuredValue
 */
class ReadTemperatureMeasurementMinMeasuredValue : public ReadAttribute {
public:
    ReadTemperatureMeasurementMinMeasuredValue()
        : ReadAttribute("min-measured-value")
    {
    }

    ~ReadTemperatureMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMinMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.MinMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement MinMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementMinMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementMinMeasuredValue()
        : SubscribeAttribute("min-measured-value")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.MinMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxMeasuredValue
 */
class ReadTemperatureMeasurementMaxMeasuredValue : public ReadAttribute {
public:
    ReadTemperatureMeasurementMaxMeasuredValue()
        : ReadAttribute("max-measured-value")
    {
    }

    ~ReadTemperatureMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.MaxMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement MaxMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementMaxMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementMaxMeasuredValue()
        : SubscribeAttribute("max-measured-value")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.MaxMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Tolerance
 */
class ReadTemperatureMeasurementTolerance : public ReadAttribute {
public:
    ReadTemperatureMeasurementTolerance()
        : ReadAttribute("tolerance")
    {
    }

    ~ReadTemperatureMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeToleranceWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.Tolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement Tolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementTolerance : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementTolerance()
        : SubscribeAttribute("tolerance")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeToleranceWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.Tolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadTemperatureMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadTemperatureMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadTemperatureMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadTemperatureMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadTemperatureMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadTemperatureMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadTemperatureMeasurementAttributeList : public ReadAttribute {
public:
    ReadTemperatureMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadTemperatureMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadTemperatureMeasurementFeatureMap : public ReadAttribute {
public:
    ReadTemperatureMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadTemperatureMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadTemperatureMeasurementClusterRevision : public ReadAttribute {
public:
    ReadTemperatureMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadTemperatureMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster PressureMeasurement                                         | 0x0403 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasuredValue                                                     | 0x0000 |
| * MinMeasuredValue                                                  | 0x0001 |
| * MaxMeasuredValue                                                  | 0x0002 |
| * Tolerance                                                         | 0x0003 |
| * ScaledValue                                                       | 0x0010 |
| * MinScaledValue                                                    | 0x0011 |
| * MaxScaledValue                                                    | 0x0012 |
| * ScaledTolerance                                                   | 0x0013 |
| * Scale                                                             | 0x0014 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MeasuredValue
 */
class ReadPressureMeasurementMeasuredValue : public ReadAttribute {
public:
    ReadPressureMeasurementMeasuredValue()
        : ReadAttribute("measured-value")
    {
    }

    ~ReadPressureMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.MeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement MeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementMeasuredValue()
        : SubscribeAttribute("measured-value")
    {
    }

    ~SubscribeAttributePressureMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.MeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinMeasuredValue
 */
class ReadPressureMeasurementMinMeasuredValue : public ReadAttribute {
public:
    ReadPressureMeasurementMinMeasuredValue()
        : ReadAttribute("min-measured-value")
    {
    }

    ~ReadPressureMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeMinMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.MinMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement MinMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementMinMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementMinMeasuredValue()
        : SubscribeAttribute("min-measured-value")
    {
    }

    ~SubscribeAttributePressureMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.MinMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxMeasuredValue
 */
class ReadPressureMeasurementMaxMeasuredValue : public ReadAttribute {
public:
    ReadPressureMeasurementMaxMeasuredValue()
        : ReadAttribute("max-measured-value")
    {
    }

    ~ReadPressureMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeMaxMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.MaxMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement MaxMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementMaxMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementMaxMeasuredValue()
        : SubscribeAttribute("max-measured-value")
    {
    }

    ~SubscribeAttributePressureMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.MaxMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Tolerance
 */
class ReadPressureMeasurementTolerance : public ReadAttribute {
public:
    ReadPressureMeasurementTolerance()
        : ReadAttribute("tolerance")
    {
    }

    ~ReadPressureMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeToleranceWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.Tolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement Tolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementTolerance : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementTolerance()
        : SubscribeAttribute("tolerance")
    {
    }

    ~SubscribeAttributePressureMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeToleranceWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.Tolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ScaledValue
 */
class ReadPressureMeasurementScaledValue : public ReadAttribute {
public:
    ReadPressureMeasurementScaledValue()
        : ReadAttribute("scaled-value")
    {
    }

    ~ReadPressureMeasurementScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeScaledValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.ScaledValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement ScaledValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementScaledValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementScaledValue()
        : SubscribeAttribute("scaled-value")
    {
    }

    ~SubscribeAttributePressureMeasurementScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeScaledValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.ScaledValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinScaledValue
 */
class ReadPressureMeasurementMinScaledValue : public ReadAttribute {
public:
    ReadPressureMeasurementMinScaledValue()
        : ReadAttribute("min-scaled-value")
    {
    }

    ~ReadPressureMeasurementMinScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeMinScaledValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.MinScaledValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement MinScaledValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementMinScaledValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementMinScaledValue()
        : SubscribeAttribute("min-scaled-value")
    {
    }

    ~SubscribeAttributePressureMeasurementMinScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinScaledValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.MinScaledValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxScaledValue
 */
class ReadPressureMeasurementMaxScaledValue : public ReadAttribute {
public:
    ReadPressureMeasurementMaxScaledValue()
        : ReadAttribute("max-scaled-value")
    {
    }

    ~ReadPressureMeasurementMaxScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeMaxScaledValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.MaxScaledValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement MaxScaledValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementMaxScaledValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementMaxScaledValue()
        : SubscribeAttribute("max-scaled-value")
    {
    }

    ~SubscribeAttributePressureMeasurementMaxScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxScaledValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.MaxScaledValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ScaledTolerance
 */
class ReadPressureMeasurementScaledTolerance : public ReadAttribute {
public:
    ReadPressureMeasurementScaledTolerance()
        : ReadAttribute("scaled-tolerance")
    {
    }

    ~ReadPressureMeasurementScaledTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeScaledToleranceWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.ScaledTolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement ScaledTolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementScaledTolerance : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementScaledTolerance()
        : SubscribeAttribute("scaled-tolerance")
    {
    }

    ~SubscribeAttributePressureMeasurementScaledTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeScaledToleranceWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.ScaledTolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Scale
 */
class ReadPressureMeasurementScale : public ReadAttribute {
public:
    ReadPressureMeasurementScale()
        : ReadAttribute("scale")
    {
    }

    ~ReadPressureMeasurementScale() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeScaleWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.Scale response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement Scale read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementScale : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementScale()
        : SubscribeAttribute("scale")
    {
    }

    ~SubscribeAttributePressureMeasurementScale() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeScaleWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.Scale response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadPressureMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadPressureMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadPressureMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributePressureMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadPressureMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadPressureMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadPressureMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributePressureMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadPressureMeasurementAttributeList : public ReadAttribute {
public:
    ReadPressureMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadPressureMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributePressureMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadPressureMeasurementFeatureMap : public ReadAttribute {
public:
    ReadPressureMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadPressureMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributePressureMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadPressureMeasurementClusterRevision : public ReadAttribute {
public:
    ReadPressureMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadPressureMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributePressureMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster FlowMeasurement                                             | 0x0404 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasuredValue                                                     | 0x0000 |
| * MinMeasuredValue                                                  | 0x0001 |
| * MaxMeasuredValue                                                  | 0x0002 |
| * Tolerance                                                         | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MeasuredValue
 */
class ReadFlowMeasurementMeasuredValue : public ReadAttribute {
public:
    ReadFlowMeasurementMeasuredValue()
        : ReadAttribute("measured-value")
    {
    }

    ~ReadFlowMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.MeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement MeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementMeasuredValue()
        : SubscribeAttribute("measured-value")
    {
    }

    ~SubscribeAttributeFlowMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.MeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinMeasuredValue
 */
class ReadFlowMeasurementMinMeasuredValue : public ReadAttribute {
public:
    ReadFlowMeasurementMinMeasuredValue()
        : ReadAttribute("min-measured-value")
    {
    }

    ~ReadFlowMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeMinMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.MinMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement MinMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementMinMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementMinMeasuredValue()
        : SubscribeAttribute("min-measured-value")
    {
    }

    ~SubscribeAttributeFlowMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.MinMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxMeasuredValue
 */
class ReadFlowMeasurementMaxMeasuredValue : public ReadAttribute {
public:
    ReadFlowMeasurementMaxMeasuredValue()
        : ReadAttribute("max-measured-value")
    {
    }

    ~ReadFlowMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeMaxMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.MaxMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement MaxMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementMaxMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementMaxMeasuredValue()
        : SubscribeAttribute("max-measured-value")
    {
    }

    ~SubscribeAttributeFlowMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.MaxMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Tolerance
 */
class ReadFlowMeasurementTolerance : public ReadAttribute {
public:
    ReadFlowMeasurementTolerance()
        : ReadAttribute("tolerance")
    {
    }

    ~ReadFlowMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeToleranceWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.Tolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement Tolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementTolerance : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementTolerance()
        : SubscribeAttribute("tolerance")
    {
    }

    ~SubscribeAttributeFlowMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeToleranceWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.Tolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadFlowMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadFlowMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadFlowMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeFlowMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadFlowMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadFlowMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadFlowMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeFlowMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadFlowMeasurementAttributeList : public ReadAttribute {
public:
    ReadFlowMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadFlowMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeFlowMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadFlowMeasurementFeatureMap : public ReadAttribute {
public:
    ReadFlowMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadFlowMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeFlowMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadFlowMeasurementClusterRevision : public ReadAttribute {
public:
    ReadFlowMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadFlowMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeFlowMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster RelativeHumidityMeasurement                                 | 0x0405 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasuredValue                                                     | 0x0000 |
| * MinMeasuredValue                                                  | 0x0001 |
| * MaxMeasuredValue                                                  | 0x0002 |
| * Tolerance                                                         | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MeasuredValue
 */
class ReadRelativeHumidityMeasurementMeasuredValue : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementMeasuredValue()
        : ReadAttribute("measured-value")
    {
    }

    ~ReadRelativeHumidityMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.MeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement MeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementMeasuredValue()
        : SubscribeAttribute("measured-value")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.MeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinMeasuredValue
 */
class ReadRelativeHumidityMeasurementMinMeasuredValue : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementMinMeasuredValue()
        : ReadAttribute("min-measured-value")
    {
    }

    ~ReadRelativeHumidityMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMinMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.MinMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement MinMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementMinMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementMinMeasuredValue()
        : SubscribeAttribute("min-measured-value")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMinMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.MinMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxMeasuredValue
 */
class ReadRelativeHumidityMeasurementMaxMeasuredValue : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementMaxMeasuredValue()
        : ReadAttribute("max-measured-value")
    {
    }

    ~ReadRelativeHumidityMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeMaxMeasuredValueWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.MaxMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement MaxMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementMaxMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementMaxMeasuredValue()
        : SubscribeAttribute("max-measured-value")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMaxMeasuredValueWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.MaxMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Tolerance
 */
class ReadRelativeHumidityMeasurementTolerance : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementTolerance()
        : ReadAttribute("tolerance")
    {
    }

    ~ReadRelativeHumidityMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeToleranceWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.Tolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement Tolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementTolerance : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementTolerance()
        : SubscribeAttribute("tolerance")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeToleranceWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.Tolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadRelativeHumidityMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadRelativeHumidityMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadRelativeHumidityMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadRelativeHumidityMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadRelativeHumidityMeasurementAttributeList : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadRelativeHumidityMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadRelativeHumidityMeasurementFeatureMap : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadRelativeHumidityMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadRelativeHumidityMeasurementClusterRevision : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadRelativeHumidityMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpoint:endpointId queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OccupancySensing                                            | 0x0406 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Occupancy                                                         | 0x0000 |
| * OccupancySensorType                                               | 0x0001 |
| * OccupancySensorTypeBitmap                                         | 0x0002 |
| * PirOccupiedToUnoccupiedDelay                                      | 0x0010 |
| * PirUnoccupiedToOccupiedDelay                                      | 0x0011 |
| * PirUnoccupiedToOccupiedThreshold                                  | 0x0012 |
| * UltrasonicOccupiedToUnoccupiedDelay                               | 0x0020 |
| * UltrasonicUnoccupiedToOccupiedDelay                               | 0x0021 |
| * UltrasonicUnoccupiedToOccupiedThreshold                           | 0x0022 |
| * PhysicalContactOccupiedToUnoccupiedDelay                          | 0x0030 |
| * PhysicalContactUnoccupiedToOccupiedDelay                          | 0x0031 |
| * PhysicalContactUnoccupiedToOccupiedThreshold                      | 0x0032 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute Occupancy
 */
class ReadOccupancySensingOccupancy : public ReadAttribute {
public:
    ReadOccupancySensingOccupancy()
        : ReadAttribute("occupancy")
    {
    }

    ~ReadOccupancySensingOccupancy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeOccupancyWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.Occupancy response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing Occupancy read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingOccupancy : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingOccupancy()
        : SubscribeAttribute("occupancy")
    {
    }

    ~SubscribeAttributeOccupancySensingOccupancy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOccupancyWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.Occupancy response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupancySensorType
 */
class ReadOccupancySensingOccupancySensorType : public ReadAttribute {
public:
    ReadOccupancySensingOccupancySensorType()
        : ReadAttribute("occupancy-sensor-type")
    {
    }

    ~ReadOccupancySensingOccupancySensorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeOccupancySensorTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.OccupancySensorType response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing OccupancySensorType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingOccupancySensorType : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingOccupancySensorType()
        : SubscribeAttribute("occupancy-sensor-type")
    {
    }

    ~SubscribeAttributeOccupancySensingOccupancySensorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOccupancySensorTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.OccupancySensorType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupancySensorTypeBitmap
 */
class ReadOccupancySensingOccupancySensorTypeBitmap : public ReadAttribute {
public:
    ReadOccupancySensingOccupancySensorTypeBitmap()
        : ReadAttribute("occupancy-sensor-type-bitmap")
    {
    }

    ~ReadOccupancySensingOccupancySensorTypeBitmap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster
            readAttributeOccupancySensorTypeBitmapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.OccupancySensorTypeBitmap response %@", [value description]);
                if (error != nil) {
                    LogNSError("OccupancySensing OccupancySensorTypeBitmap read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingOccupancySensorTypeBitmap : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingOccupancySensorTypeBitmap()
        : SubscribeAttribute("occupancy-sensor-type-bitmap")
    {
    }

    ~SubscribeAttributeOccupancySensingOccupancySensorTypeBitmap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOccupancySensorTypeBitmapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.OccupancySensorTypeBitmap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PirOccupiedToUnoccupiedDelay
 */
class ReadOccupancySensingPirOccupiedToUnoccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingPirOccupiedToUnoccupiedDelay()
        : ReadAttribute("pir-occupied-to-unoccupied-delay")
    {
    }

    ~ReadOccupancySensingPirOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributePirOccupiedToUnoccupiedDelayWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PirOccupiedToUnoccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PirOccupiedToUnoccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPirOccupiedToUnoccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingPirOccupiedToUnoccupiedDelay()
        : WriteAttribute("pir-occupied-to-unoccupied-delay")
    {
        AddArgument("attr-name", "pir-occupied-to-unoccupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPirOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributePirOccupiedToUnoccupiedDelayWithValue:value
                                                              params:params
                                                   completionHandler:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError(
                                                               "OccupancySensing PirOccupiedToUnoccupiedDelay write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingPirOccupiedToUnoccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPirOccupiedToUnoccupiedDelay()
        : SubscribeAttribute("pir-occupied-to-unoccupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingPirOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePirOccupiedToUnoccupiedDelayWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PirOccupiedToUnoccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PirUnoccupiedToOccupiedDelay
 */
class ReadOccupancySensingPirUnoccupiedToOccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingPirUnoccupiedToOccupiedDelay()
        : ReadAttribute("pir-unoccupied-to-occupied-delay")
    {
    }

    ~ReadOccupancySensingPirUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributePirUnoccupiedToOccupiedDelayWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PirUnoccupiedToOccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PirUnoccupiedToOccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPirUnoccupiedToOccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingPirUnoccupiedToOccupiedDelay()
        : WriteAttribute("pir-unoccupied-to-occupied-delay")
    {
        AddArgument("attr-name", "pir-unoccupied-to-occupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPirUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributePirUnoccupiedToOccupiedDelayWithValue:value
                                                              params:params
                                                   completionHandler:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError(
                                                               "OccupancySensing PirUnoccupiedToOccupiedDelay write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedDelay()
        : SubscribeAttribute("pir-unoccupied-to-occupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePirUnoccupiedToOccupiedDelayWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PirUnoccupiedToOccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PirUnoccupiedToOccupiedThreshold
 */
class ReadOccupancySensingPirUnoccupiedToOccupiedThreshold : public ReadAttribute {
public:
    ReadOccupancySensingPirUnoccupiedToOccupiedThreshold()
        : ReadAttribute("pir-unoccupied-to-occupied-threshold")
    {
    }

    ~ReadOccupancySensingPirUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributePirUnoccupiedToOccupiedThresholdWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PirUnoccupiedToOccupiedThreshold response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PirUnoccupiedToOccupiedThreshold read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPirUnoccupiedToOccupiedThreshold : public WriteAttribute {
public:
    WriteOccupancySensingPirUnoccupiedToOccupiedThreshold()
        : WriteAttribute("pir-unoccupied-to-occupied-threshold")
    {
        AddArgument("attr-name", "pir-unoccupied-to-occupied-threshold");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPirUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributePirUnoccupiedToOccupiedThresholdWithValue:value
                                                                  params:params
                                                       completionHandler:^(NSError * _Nullable error) {
                                                           if (error != nil) {
                                                               LogNSError(
                                                                   "OccupancySensing PirUnoccupiedToOccupiedThreshold write Error",
                                                                   error);
                                                           }
                                                           SetCommandExitStatus(error);
                                                       }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedThreshold : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedThreshold()
        : SubscribeAttribute("pir-unoccupied-to-occupied-threshold")
    {
    }

    ~SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePirUnoccupiedToOccupiedThresholdWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PirUnoccupiedToOccupiedThreshold response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UltrasonicOccupiedToUnoccupiedDelay
 */
class ReadOccupancySensingUltrasonicOccupiedToUnoccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingUltrasonicOccupiedToUnoccupiedDelay()
        : ReadAttribute("ultrasonic-occupied-to-unoccupied-delay")
    {
    }

    ~ReadOccupancySensingUltrasonicOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeUltrasonicOccupiedToUnoccupiedDelayWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.UltrasonicOccupiedToUnoccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing UltrasonicOccupiedToUnoccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingUltrasonicOccupiedToUnoccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingUltrasonicOccupiedToUnoccupiedDelay()
        : WriteAttribute("ultrasonic-occupied-to-unoccupied-delay")
    {
        AddArgument("attr-name", "ultrasonic-occupied-to-unoccupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingUltrasonicOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeUltrasonicOccupiedToUnoccupiedDelayWithValue:value
                                                                params:params
                                                     completionHandler:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError(
                                                                 "OccupancySensing UltrasonicOccupiedToUnoccupiedDelay write Error",
                                                                 error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingUltrasonicOccupiedToUnoccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingUltrasonicOccupiedToUnoccupiedDelay()
        : SubscribeAttribute("ultrasonic-occupied-to-unoccupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingUltrasonicOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUltrasonicOccupiedToUnoccupiedDelayWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.UltrasonicOccupiedToUnoccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UltrasonicUnoccupiedToOccupiedDelay
 */
class ReadOccupancySensingUltrasonicUnoccupiedToOccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingUltrasonicUnoccupiedToOccupiedDelay()
        : ReadAttribute("ultrasonic-unoccupied-to-occupied-delay")
    {
    }

    ~ReadOccupancySensingUltrasonicUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeUltrasonicUnoccupiedToOccupiedDelayWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.UltrasonicUnoccupiedToOccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing UltrasonicUnoccupiedToOccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingUltrasonicUnoccupiedToOccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingUltrasonicUnoccupiedToOccupiedDelay()
        : WriteAttribute("ultrasonic-unoccupied-to-occupied-delay")
    {
        AddArgument("attr-name", "ultrasonic-unoccupied-to-occupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingUltrasonicUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeUltrasonicUnoccupiedToOccupiedDelayWithValue:value
                                                                params:params
                                                     completionHandler:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError(
                                                                 "OccupancySensing UltrasonicUnoccupiedToOccupiedDelay write Error",
                                                                 error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedDelay()
        : SubscribeAttribute("ultrasonic-unoccupied-to-occupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUltrasonicUnoccupiedToOccupiedDelayWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.UltrasonicUnoccupiedToOccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UltrasonicUnoccupiedToOccupiedThreshold
 */
class ReadOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold : public ReadAttribute {
public:
    ReadOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold()
        : ReadAttribute("ultrasonic-unoccupied-to-occupied-threshold")
    {
    }

    ~ReadOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeUltrasonicUnoccupiedToOccupiedThresholdWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.UltrasonicUnoccupiedToOccupiedThreshold response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing UltrasonicUnoccupiedToOccupiedThreshold read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold : public WriteAttribute {
public:
    WriteOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold()
        : WriteAttribute("ultrasonic-unoccupied-to-occupied-threshold")
    {
        AddArgument("attr-name", "ultrasonic-unoccupied-to-occupied-threshold");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster
            writeAttributeUltrasonicUnoccupiedToOccupiedThresholdWithValue:value
                                                                    params:params
                                                         completionHandler:^(NSError * _Nullable error) {
                                                             if (error != nil) {
                                                                 LogNSError("OccupancySensing "
                                                                            "UltrasonicUnoccupiedToOccupiedThreshold write Error",
                                                                     error);
                                                             }
                                                             SetCommandExitStatus(error);
                                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold()
        : SubscribeAttribute("ultrasonic-unoccupied-to-occupied-threshold")
    {
    }

    ~SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster
            subscribeAttributeUltrasonicUnoccupiedToOccupiedThresholdWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.UltrasonicUnoccupiedToOccupiedThreshold response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalContactOccupiedToUnoccupiedDelay
 */
class ReadOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay()
        : ReadAttribute("physical-contact-occupied-to-unoccupied-delay")
    {
    }

    ~ReadOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributePhysicalContactOccupiedToUnoccupiedDelayWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PhysicalContactOccupiedToUnoccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PhysicalContactOccupiedToUnoccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay()
        : WriteAttribute("physical-contact-occupied-to-unoccupied-delay")
    {
        AddArgument("attr-name", "physical-contact-occupied-to-unoccupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributePhysicalContactOccupiedToUnoccupiedDelayWithValue:value
                                                                     params:params
                                                          completionHandler:^(NSError * _Nullable error) {
                                                              if (error != nil) {
                                                                  LogNSError("OccupancySensing "
                                                                             "PhysicalContactOccupiedToUnoccupiedDelay write Error",
                                                                      error);
                                                              }
                                                              SetCommandExitStatus(error);
                                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay()
        : SubscribeAttribute("physical-contact-occupied-to-unoccupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster
            subscribeAttributePhysicalContactOccupiedToUnoccupiedDelayWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PhysicalContactOccupiedToUnoccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalContactUnoccupiedToOccupiedDelay
 */
class ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay()
        : ReadAttribute("physical-contact-unoccupied-to-occupied-delay")
    {
    }

    ~ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributePhysicalContactUnoccupiedToOccupiedDelayWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PhysicalContactUnoccupiedToOccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PhysicalContactUnoccupiedToOccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay()
        : WriteAttribute("physical-contact-unoccupied-to-occupied-delay")
    {
        AddArgument("attr-name", "physical-contact-unoccupied-to-occupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributePhysicalContactUnoccupiedToOccupiedDelayWithValue:value
                                                                     params:params
                                                          completionHandler:^(NSError * _Nullable error) {
                                                              if (error != nil) {
                                                                  LogNSError("OccupancySensing "
                                                                             "PhysicalContactUnoccupiedToOccupiedDelay write Error",
                                                                      error);
                                                              }
                                                              SetCommandExitStatus(error);
                                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay()
        : SubscribeAttribute("physical-contact-unoccupied-to-occupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster
            subscribeAttributePhysicalContactUnoccupiedToOccupiedDelayWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PhysicalContactUnoccupiedToOccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalContactUnoccupiedToOccupiedThreshold
 */
class ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold : public ReadAttribute {
public:
    ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold()
        : ReadAttribute("physical-contact-unoccupied-to-occupied-threshold")
    {
    }

    ~ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributePhysicalContactUnoccupiedToOccupiedThresholdWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PhysicalContactUnoccupiedToOccupiedThreshold response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PhysicalContactUnoccupiedToOccupiedThreshold read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold : public WriteAttribute {
public:
    WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold()
        : WriteAttribute("physical-contact-unoccupied-to-occupied-threshold")
    {
        AddArgument("attr-name", "physical-contact-unoccupied-to-occupied-threshold");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributePhysicalContactUnoccupiedToOccupiedThresholdWithValue:value
                                                                              params:params
                                                                   completionHandler:^(NSError * _Nullable error) {
                                                                       if (error != nil) {
                                                                           LogNSError("OccupancySensing "
                                                                                      "PhysicalContactUnoccupiedToOccupiedThreshold"
                                                                                      " write Error",
                                                                               error);
                                                                       }
                                                                       SetCommandExitStatus(error);
                                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold()
        : SubscribeAttribute("physical-contact-unoccupied-to-occupied-threshold")
    {
    }

    ~SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster
            subscribeAttributePhysicalContactUnoccupiedToOccupiedThresholdWithMinInterval:[NSNumber
                                                                                              numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PhysicalContactUnoccupiedToOccupiedThreshold response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadOccupancySensingGeneratedCommandList : public ReadAttribute {
public:
    ReadOccupancySensingGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadOccupancySensingGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeOccupancySensingGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadOccupancySensingAcceptedCommandList : public ReadAttribute {
public:
    ReadOccupancySensingAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadOccupancySensingAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeOccupancySensingAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadOccupancySensingAttributeList : public ReadAttribute {
public:
    ReadOccupancySensingAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadOccupancySensingAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeOccupancySensingAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadOccupancySensingFeatureMap : public ReadAttribute {
public:
    ReadOccupancySensingFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadOccupancySensingFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeOccupancySensingFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadOccupancySensingClusterRevision : public ReadAttribute {
public:
    ReadOccupancySensingClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadOccupancySensingClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeOccupancySensingClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster WakeOnLan                                                   | 0x0503 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MACAddress                                                        | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MACAddress
 */
class ReadWakeOnLanMACAddress : public ReadAttribute {
public:
    ReadWakeOnLanMACAddress()
        : ReadAttribute("macaddress")
    {
    }

    ~ReadWakeOnLanMACAddress() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeMACAddressWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.MACAddress response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan MACAddress read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanMACAddress : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanMACAddress()
        : SubscribeAttribute("macaddress")
    {
    }

    ~SubscribeAttributeWakeOnLanMACAddress() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMACAddressWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.MACAddress response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadWakeOnLanGeneratedCommandList : public ReadAttribute {
public:
    ReadWakeOnLanGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadWakeOnLanGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeWakeOnLanGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadWakeOnLanAcceptedCommandList : public ReadAttribute {
public:
    ReadWakeOnLanAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadWakeOnLanAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeWakeOnLanAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadWakeOnLanAttributeList : public ReadAttribute {
public:
    ReadWakeOnLanAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadWakeOnLanAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeWakeOnLanAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadWakeOnLanFeatureMap : public ReadAttribute {
public:
    ReadWakeOnLanFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadWakeOnLanFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeWakeOnLanFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadWakeOnLanClusterRevision : public ReadAttribute {
public:
    ReadWakeOnLanClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadWakeOnLanClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeWakeOnLanClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                   endpoint:endpointId
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Channel                                                     | 0x0504 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ChangeChannel                                                     |   0x00 |
| * ChangeChannelByNumber                                             |   0x02 |
| * SkipChannel                                                       |   0x03 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * ChannelList                                                       | 0x0000 |
| * Lineup                                                            | 0x0001 |
| * CurrentChannel                                                    | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ChangeChannel
 */
class ChannelChangeChannel : public ClusterCommand {
public:
    ChannelChangeChannel()
        : ClusterCommand("change-channel")
    {
        AddArgument("Match", &mRequest.match);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint: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
                           completionHandler:^(
                               MTRChannelClusterChangeChannelResponseParams * _Nullable values, NSError * _Nullable error) {
                               NSLog(@"Values: %@", values);
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Channel::Commands::ChangeChannel::Type mRequest;
};

/*
 * Command ChangeChannelByNumber
 */
class ChannelChangeChannelByNumber : public ClusterCommand {
public:
    ChannelChangeChannelByNumber()
        : ClusterCommand("change-channel-by-number")
    {
        AddArgument("MajorNumber", 0, UINT16_MAX, &mRequest.majorNumber);
        AddArgument("MinorNumber", 0, UINT16_MAX, &mRequest.minorNumber);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint: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
                                   completionHandler:^(NSError * _Nullable error) {
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Channel::Commands::ChangeChannelByNumber::Type mRequest;
};

/*
 * Command SkipChannel
 */
class ChannelSkipChannel : public ClusterCommand {
public:
    ChannelSkipChannel()
        : ClusterCommand("skip-channel")
    {
        AddArgument("Count", 0, UINT16_MAX, &mRequest.count);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRChannelClusterSkipChannelParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.count = [NSNumber numberWithUnsignedShort:mRequest.count];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster skipChannelWithParams:params
                         completionHandler:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Channel::Commands::SkipChannel::Type mRequest;
};

/*
 * Attribute ChannelList
 */
class ReadChannelChannelList : public ReadAttribute {
public:
    ReadChannelChannelList()
        : ReadAttribute("channel-list")
    {
    }

    ~ReadChannelChannelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        [cluster readAttributeChannelListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.ChannelList response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel ChannelList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelChannelList : public SubscribeAttribute {
public:
    SubscribeAttributeChannelChannelList()
        : SubscribeAttribute("channel-list")
    {
    }

    ~SubscribeAttributeChannelChannelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeChannelListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.ChannelList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Lineup
 */
class ReadChannelLineup : public ReadAttribute {
public:
    ReadChannelLineup()
        : ReadAttribute("lineup")
    {
    }

    ~ReadChannelLineup() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        [cluster
            readAttributeLineupWithCompletionHandler:^(MTRChannelClusterLineupInfo * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.Lineup response %@", [value description]);
                if (error != nil) {
                    LogNSError("Channel Lineup read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelLineup : public SubscribeAttribute {
public:
    SubscribeAttributeChannelLineup()
        : SubscribeAttribute("lineup")
    {
    }

    ~SubscribeAttributeChannelLineup() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLineupWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRChannelClusterLineupInfo * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.Lineup response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentChannel
 */
class ReadChannelCurrentChannel : public ReadAttribute {
public:
    ReadChannelCurrentChannel()
        : ReadAttribute("current-channel")
    {
    }

    ~ReadChannelCurrentChannel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        [cluster readAttributeCurrentChannelWithCompletionHandler:^(
            MTRChannelClusterChannelInfo * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.CurrentChannel response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel CurrentChannel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelCurrentChannel : public SubscribeAttribute {
public:
    SubscribeAttributeChannelCurrentChannel()
        : SubscribeAttribute("current-channel")
    {
    }

    ~SubscribeAttributeChannelCurrentChannel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentChannelWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRChannelClusterChannelInfo * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.CurrentChannel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadChannelGeneratedCommandList : public ReadAttribute {
public:
    ReadChannelGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadChannelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeChannelGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeChannelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadChannelAcceptedCommandList : public ReadAttribute {
public:
    ReadChannelAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadChannelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeChannelAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeChannelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadChannelAttributeList : public ReadAttribute {
public:
    ReadChannelAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadChannelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeChannelAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeChannelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadChannelFeatureMap : public ReadAttribute {
public:
    ReadChannelFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadChannelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeChannelFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeChannelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadChannelClusterRevision : public ReadAttribute {
public:
    ReadChannelClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadChannelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeChannelClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeChannelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                               endpoint:endpointId
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster TargetNavigator                                             | 0x0505 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * NavigateTarget                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * TargetList                                                        | 0x0000 |
| * CurrentTarget                                                     | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command NavigateTarget
 */
class TargetNavigatorNavigateTarget : public ClusterCommand {
public:
    TargetNavigatorNavigateTarget()
        : ClusterCommand("navigate-target")
    {
        AddArgument("Target", 0, UINT8_MAX, &mRequest.target);
        AddArgument("Data", &mRequest.data);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint: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
                            completionHandler:^(MTRTargetNavigatorClusterNavigateTargetResponseParams * _Nullable values,
                                NSError * _Nullable error) {
                                NSLog(@"Values: %@", values);
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TargetNavigator::Commands::NavigateTarget::Type mRequest;
};

/*
 * Attribute TargetList
 */
class ReadTargetNavigatorTargetList : public ReadAttribute {
public:
    ReadTargetNavigatorTargetList()
        : ReadAttribute("target-list")
    {
    }

    ~ReadTargetNavigatorTargetList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeTargetListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.TargetList response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator TargetList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorTargetList : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorTargetList()
        : SubscribeAttribute("target-list")
    {
    }

    ~SubscribeAttributeTargetNavigatorTargetList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTargetListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.TargetList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentTarget
 */
class ReadTargetNavigatorCurrentTarget : public ReadAttribute {
public:
    ReadTargetNavigatorCurrentTarget()
        : ReadAttribute("current-target")
    {
    }

    ~ReadTargetNavigatorCurrentTarget() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeCurrentTargetWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.CurrentTarget response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator CurrentTarget read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorCurrentTarget : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorCurrentTarget()
        : SubscribeAttribute("current-target")
    {
    }

    ~SubscribeAttributeTargetNavigatorCurrentTarget() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentTargetWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.CurrentTarget response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadTargetNavigatorGeneratedCommandList : public ReadAttribute {
public:
    ReadTargetNavigatorGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadTargetNavigatorGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeTargetNavigatorGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadTargetNavigatorAcceptedCommandList : public ReadAttribute {
public:
    ReadTargetNavigatorAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadTargetNavigatorAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeTargetNavigatorAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadTargetNavigatorAttributeList : public ReadAttribute {
public:
    ReadTargetNavigatorAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadTargetNavigatorAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeTargetNavigatorAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadTargetNavigatorFeatureMap : public ReadAttribute {
public:
    ReadTargetNavigatorFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadTargetNavigatorFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeTargetNavigatorFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadTargetNavigatorClusterRevision : public ReadAttribute {
public:
    ReadTargetNavigatorClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadTargetNavigatorClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeTargetNavigatorClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster MediaPlayback                                               | 0x0506 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * Play                                                              |   0x00 |
| * Pause                                                             |   0x01 |
| * StopPlayback                                                      |   0x02 |
| * StartOver                                                         |   0x03 |
| * Previous                                                          |   0x04 |
| * Next                                                              |   0x05 |
| * Rewind                                                            |   0x06 |
| * FastForward                                                       |   0x07 |
| * SkipForward                                                       |   0x08 |
| * SkipBackward                                                      |   0x09 |
| * Seek                                                              |   0x0B |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * CurrentState                                                      | 0x0000 |
| * StartTime                                                         | 0x0001 |
| * Duration                                                          | 0x0002 |
| * SampledPosition                                                   | 0x0003 |
| * PlaybackSpeed                                                     | 0x0004 |
| * SeekRangeEnd                                                      | 0x0005 |
| * SeekRangeStart                                                    | 0x0006 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command Play
 */
class MediaPlaybackPlay : public ClusterCommand {
public:
    MediaPlaybackPlay()
        : ClusterCommand("play")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint: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
                  completionHandler:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                      NSLog(@"Values: %@", values);
                      responsesNeeded--;
                      if (error != nil) {
                          mError = error;
                          LogNSError("Error", error);
                      }
                      if (responsesNeeded == 0) {
                          SetCommandExitStatus(mError);
                      }
                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command Pause
 */
class MediaPlaybackPause : public ClusterCommand {
public:
    MediaPlaybackPause()
        : ClusterCommand("pause")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint: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
                completionHandler:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                    NSLog(@"Values: %@", values);
                    responsesNeeded--;
                    if (error != nil) {
                        mError = error;
                        LogNSError("Error", error);
                    }
                    if (responsesNeeded == 0) {
                        SetCommandExitStatus(mError);
                    }
                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command StopPlayback
 */
class MediaPlaybackStopPlayback : public ClusterCommand {
public:
    MediaPlaybackStopPlayback()
        : ClusterCommand("stop-playback")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterStopPlaybackParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stopPlaybackWithParams:params
                          completionHandler:^(
                              MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                              NSLog(@"Values: %@", values);
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command StartOver
 */
class MediaPlaybackStartOver : public ClusterCommand {
public:
    MediaPlaybackStartOver()
        : ClusterCommand("start-over")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint: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
                  completionHandler:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                      NSLog(@"Values: %@", values);
                      responsesNeeded--;
                      if (error != nil) {
                          mError = error;
                          LogNSError("Error", error);
                      }
                      if (responsesNeeded == 0) {
                          SetCommandExitStatus(mError);
                      }
                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command Previous
 */
class MediaPlaybackPrevious : public ClusterCommand {
public:
    MediaPlaybackPrevious()
        : ClusterCommand("previous")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint: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
                 completionHandler:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                     NSLog(@"Values: %@", values);
                     responsesNeeded--;
                     if (error != nil) {
                         mError = error;
                         LogNSError("Error", error);
                     }
                     if (responsesNeeded == 0) {
                         SetCommandExitStatus(mError);
                     }
                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command Next
 */
class MediaPlaybackNext : public ClusterCommand {
public:
    MediaPlaybackNext()
        : ClusterCommand("next")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint: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
                  completionHandler:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                      NSLog(@"Values: %@", values);
                      responsesNeeded--;
                      if (error != nil) {
                          mError = error;
                          LogNSError("Error", error);
                      }
                      if (responsesNeeded == 0) {
                          SetCommandExitStatus(mError);
                      }
                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command Rewind
 */
class MediaPlaybackRewind : public ClusterCommand {
public:
    MediaPlaybackRewind()
        : ClusterCommand("rewind")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint: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
                completionHandler:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                    NSLog(@"Values: %@", values);
                    responsesNeeded--;
                    if (error != nil) {
                        mError = error;
                        LogNSError("Error", error);
                    }
                    if (responsesNeeded == 0) {
                        SetCommandExitStatus(mError);
                    }
                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command FastForward
 */
class MediaPlaybackFastForward : public ClusterCommand {
public:
    MediaPlaybackFastForward()
        : ClusterCommand("fast-forward")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint: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
                         completionHandler:^(
                             MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                             NSLog(@"Values: %@", values);
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command SkipForward
 */
class MediaPlaybackSkipForward : public ClusterCommand {
public:
    MediaPlaybackSkipForward()
        : ClusterCommand("skip-forward")
    {
        AddArgument("DeltaPositionMilliseconds", 0, UINT64_MAX, &mRequest.deltaPositionMilliseconds);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint: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
                         completionHandler:^(
                             MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                             NSLog(@"Values: %@", values);
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::MediaPlayback::Commands::SkipForward::Type mRequest;
};

/*
 * Command SkipBackward
 */
class MediaPlaybackSkipBackward : public ClusterCommand {
public:
    MediaPlaybackSkipBackward()
        : ClusterCommand("skip-backward")
    {
        AddArgument("DeltaPositionMilliseconds", 0, UINT64_MAX, &mRequest.deltaPositionMilliseconds);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint: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
                          completionHandler:^(
                              MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                              NSLog(@"Values: %@", values);
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::MediaPlayback::Commands::SkipBackward::Type mRequest;
};

/*
 * Command Seek
 */
class MediaPlaybackSeek : public ClusterCommand {
public:
    MediaPlaybackSeek()
        : ClusterCommand("seek")
    {
        AddArgument("Position", 0, UINT64_MAX, &mRequest.position);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint: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
                  completionHandler:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                      NSLog(@"Values: %@", values);
                      responsesNeeded--;
                      if (error != nil) {
                          mError = error;
                          LogNSError("Error", error);
                      }
                      if (responsesNeeded == 0) {
                          SetCommandExitStatus(mError);
                      }
                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::MediaPlayback::Commands::Seek::Type mRequest;
};

/*
 * Attribute CurrentState
 */
class ReadMediaPlaybackCurrentState : public ReadAttribute {
public:
    ReadMediaPlaybackCurrentState()
        : ReadAttribute("current-state")
    {
    }

    ~ReadMediaPlaybackCurrentState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeCurrentStateWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.CurrentState response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback CurrentState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackCurrentState : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackCurrentState()
        : SubscribeAttribute("current-state")
    {
    }

    ~SubscribeAttributeMediaPlaybackCurrentState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentStateWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.CurrentState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StartTime
 */
class ReadMediaPlaybackStartTime : public ReadAttribute {
public:
    ReadMediaPlaybackStartTime()
        : ReadAttribute("start-time")
    {
    }

    ~ReadMediaPlaybackStartTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeStartTimeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.StartTime response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback StartTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackStartTime : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackStartTime()
        : SubscribeAttribute("start-time")
    {
    }

    ~SubscribeAttributeMediaPlaybackStartTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeStartTimeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.StartTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Duration
 */
class ReadMediaPlaybackDuration : public ReadAttribute {
public:
    ReadMediaPlaybackDuration()
        : ReadAttribute("duration")
    {
    }

    ~ReadMediaPlaybackDuration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeDurationWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.Duration response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback Duration read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackDuration : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackDuration()
        : SubscribeAttribute("duration")
    {
    }

    ~SubscribeAttributeMediaPlaybackDuration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDurationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.Duration response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SampledPosition
 */
class ReadMediaPlaybackSampledPosition : public ReadAttribute {
public:
    ReadMediaPlaybackSampledPosition()
        : ReadAttribute("sampled-position")
    {
    }

    ~ReadMediaPlaybackSampledPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeSampledPositionWithCompletionHandler:^(
            MTRMediaPlaybackClusterPlaybackPosition * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.SampledPosition response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback SampledPosition read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackSampledPosition : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackSampledPosition()
        : SubscribeAttribute("sampled-position")
    {
    }

    ~SubscribeAttributeMediaPlaybackSampledPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSampledPositionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRMediaPlaybackClusterPlaybackPosition * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.SampledPosition response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PlaybackSpeed
 */
class ReadMediaPlaybackPlaybackSpeed : public ReadAttribute {
public:
    ReadMediaPlaybackPlaybackSpeed()
        : ReadAttribute("playback-speed")
    {
    }

    ~ReadMediaPlaybackPlaybackSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributePlaybackSpeedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.PlaybackSpeed response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback PlaybackSpeed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackPlaybackSpeed : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackPlaybackSpeed()
        : SubscribeAttribute("playback-speed")
    {
    }

    ~SubscribeAttributeMediaPlaybackPlaybackSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePlaybackSpeedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.PlaybackSpeed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SeekRangeEnd
 */
class ReadMediaPlaybackSeekRangeEnd : public ReadAttribute {
public:
    ReadMediaPlaybackSeekRangeEnd()
        : ReadAttribute("seek-range-end")
    {
    }

    ~ReadMediaPlaybackSeekRangeEnd() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeSeekRangeEndWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.SeekRangeEnd response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback SeekRangeEnd read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackSeekRangeEnd : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackSeekRangeEnd()
        : SubscribeAttribute("seek-range-end")
    {
    }

    ~SubscribeAttributeMediaPlaybackSeekRangeEnd() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSeekRangeEndWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.SeekRangeEnd response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SeekRangeStart
 */
class ReadMediaPlaybackSeekRangeStart : public ReadAttribute {
public:
    ReadMediaPlaybackSeekRangeStart()
        : ReadAttribute("seek-range-start")
    {
    }

    ~ReadMediaPlaybackSeekRangeStart() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeSeekRangeStartWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.SeekRangeStart response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback SeekRangeStart read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackSeekRangeStart : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackSeekRangeStart()
        : SubscribeAttribute("seek-range-start")
    {
    }

    ~SubscribeAttributeMediaPlaybackSeekRangeStart() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSeekRangeStartWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.SeekRangeStart response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadMediaPlaybackGeneratedCommandList : public ReadAttribute {
public:
    ReadMediaPlaybackGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadMediaPlaybackGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeMediaPlaybackGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadMediaPlaybackAcceptedCommandList : public ReadAttribute {
public:
    ReadMediaPlaybackAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadMediaPlaybackAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeMediaPlaybackAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadMediaPlaybackAttributeList : public ReadAttribute {
public:
    ReadMediaPlaybackAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadMediaPlaybackAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeMediaPlaybackAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadMediaPlaybackFeatureMap : public ReadAttribute {
public:
    ReadMediaPlaybackFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadMediaPlaybackFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeMediaPlaybackFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadMediaPlaybackClusterRevision : public ReadAttribute {
public:
    ReadMediaPlaybackClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadMediaPlaybackClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeMediaPlaybackClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                           endpoint:endpointId
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster MediaInput                                                  | 0x0507 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * SelectInput                                                       |   0x00 |
| * ShowInputStatus                                                   |   0x01 |
| * HideInputStatus                                                   |   0x02 |
| * RenameInput                                                       |   0x03 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * InputList                                                         | 0x0000 |
| * CurrentInput                                                      | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command SelectInput
 */
class MediaInputSelectInput : public ClusterCommand {
public:
    MediaInputSelectInput()
        : ClusterCommand("select-input")
    {
        AddArgument("Index", 0, UINT8_MAX, &mRequest.index);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint: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
                         completionHandler:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::MediaInput::Commands::SelectInput::Type mRequest;
};

/*
 * Command ShowInputStatus
 */
class MediaInputShowInputStatus : public ClusterCommand {
public:
    MediaInputShowInputStatus()
        : ClusterCommand("show-input-status")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint: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
                             completionHandler:^(NSError * _Nullable error) {
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command HideInputStatus
 */
class MediaInputHideInputStatus : public ClusterCommand {
public:
    MediaInputHideInputStatus()
        : ClusterCommand("hide-input-status")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint: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
                             completionHandler:^(NSError * _Nullable error) {
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command RenameInput
 */
class MediaInputRenameInput : public ClusterCommand {
public:
    MediaInputRenameInput()
        : ClusterCommand("rename-input")
    {
        AddArgument("Index", 0, UINT8_MAX, &mRequest.index);
        AddArgument("Name", &mRequest.name);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint: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
                         completionHandler:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::MediaInput::Commands::RenameInput::Type mRequest;
};

/*
 * Attribute InputList
 */
class ReadMediaInputInputList : public ReadAttribute {
public:
    ReadMediaInputInputList()
        : ReadAttribute("input-list")
    {
    }

    ~ReadMediaInputInputList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeInputListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.InputList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput InputList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputInputList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputInputList()
        : SubscribeAttribute("input-list")
    {
    }

    ~SubscribeAttributeMediaInputInputList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInputListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.InputList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentInput
 */
class ReadMediaInputCurrentInput : public ReadAttribute {
public:
    ReadMediaInputCurrentInput()
        : ReadAttribute("current-input")
    {
    }

    ~ReadMediaInputCurrentInput() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeCurrentInputWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.CurrentInput response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput CurrentInput read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputCurrentInput : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputCurrentInput()
        : SubscribeAttribute("current-input")
    {
    }

    ~SubscribeAttributeMediaInputCurrentInput() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentInputWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.CurrentInput response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadMediaInputGeneratedCommandList : public ReadAttribute {
public:
    ReadMediaInputGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadMediaInputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeMediaInputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadMediaInputAcceptedCommandList : public ReadAttribute {
public:
    ReadMediaInputAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadMediaInputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeMediaInputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadMediaInputAttributeList : public ReadAttribute {
public:
    ReadMediaInputAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadMediaInputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeMediaInputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadMediaInputFeatureMap : public ReadAttribute {
public:
    ReadMediaInputFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadMediaInputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeMediaInputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadMediaInputClusterRevision : public ReadAttribute {
public:
    ReadMediaInputClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadMediaInputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeMediaInputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                     endpoint:endpointId
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster LowPower                                                    | 0x0508 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * Sleep                                                             |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command Sleep
 */
class LowPowerSleep : public ClusterCommand {
public:
    LowPowerSleep()
        : ClusterCommand("sleep")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint: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
                   completionHandler:^(NSError * _Nullable error) {
                       responsesNeeded--;
                       if (error != nil) {
                           mError = error;
                           LogNSError("Error", error);
                       }
                       if (responsesNeeded == 0) {
                           SetCommandExitStatus(mError);
                       }
                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute GeneratedCommandList
 */
class ReadLowPowerGeneratedCommandList : public ReadAttribute {
public:
    ReadLowPowerGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadLowPowerGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeLowPowerGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadLowPowerAcceptedCommandList : public ReadAttribute {
public:
    ReadLowPowerAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadLowPowerAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeLowPowerAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadLowPowerAttributeList : public ReadAttribute {
public:
    ReadLowPowerAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadLowPowerAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeLowPowerAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadLowPowerFeatureMap : public ReadAttribute {
public:
    ReadLowPowerFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadLowPowerFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeLowPowerFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadLowPowerClusterRevision : public ReadAttribute {
public:
    ReadLowPowerClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadLowPowerClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeLowPowerClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                                 endpoint:endpointId
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster KeypadInput                                                 | 0x0509 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * SendKey                                                           |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command SendKey
 */
class KeypadInputSendKey : public ClusterCommand {
public:
    KeypadInputSendKey()
        : ClusterCommand("send-key")
    {
        AddArgument("KeyCode", 0, UINT8_MAX, &mRequest.keyCode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint: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
                     completionHandler:^(MTRKeypadInputClusterSendKeyResponseParams * _Nullable values, NSError * _Nullable error) {
                         NSLog(@"Values: %@", values);
                         responsesNeeded--;
                         if (error != nil) {
                             mError = error;
                             LogNSError("Error", error);
                         }
                         if (responsesNeeded == 0) {
                             SetCommandExitStatus(mError);
                         }
                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::KeypadInput::Commands::SendKey::Type mRequest;
};

/*
 * Attribute GeneratedCommandList
 */
class ReadKeypadInputGeneratedCommandList : public ReadAttribute {
public:
    ReadKeypadInputGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadKeypadInputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeKeypadInputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadKeypadInputAcceptedCommandList : public ReadAttribute {
public:
    ReadKeypadInputAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadKeypadInputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeKeypadInputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadKeypadInputAttributeList : public ReadAttribute {
public:
    ReadKeypadInputAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadKeypadInputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeKeypadInputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadKeypadInputFeatureMap : public ReadAttribute {
public:
    ReadKeypadInputFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadKeypadInputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeKeypadInputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadKeypadInputClusterRevision : public ReadAttribute {
public:
    ReadKeypadInputClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadKeypadInputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeKeypadInputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ContentLauncher                                             | 0x050A |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * LaunchContent                                                     |   0x00 |
| * LaunchURL                                                         |   0x01 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * AcceptHeader                                                      | 0x0000 |
| * SupportedStreamingProtocols                                       | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command LaunchContent
 */
class ContentLauncherLaunchContent : public ClusterCommand {
public:
    ContentLauncherLaunchContent()
        : ClusterCommand("launch-content")
        , mComplex_Search(&mRequest.search)
    {
        AddArgument("Search", &mComplex_Search);
        AddArgument("AutoPlay", 0, 1, &mRequest.autoPlay);
        AddArgument("Data", &mRequest.data);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRContentLauncherClusterLaunchContentParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.search = [MTRContentLauncherClusterContentSearch new];
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.search.parameterList) {
                MTRContentLauncherClusterParameter * newElement_1;
                newElement_1 = [MTRContentLauncherClusterParameter new];
                newElement_1.type = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_1.type)];
                newElement_1.value = [[NSString alloc] initWithBytes:entry_1.value.data()
                                                              length:entry_1.value.size()
                                                            encoding:NSUTF8StringEncoding];
                if (entry_1.externalIDList.HasValue()) {
                    { // Scope for our temporary variables
                        auto * array_4 = [NSMutableArray new];
                        for (auto & entry_4 : entry_1.externalIDList.Value()) {
                            MTRContentLauncherClusterAdditionalInfo * newElement_4;
                            newElement_4 = [MTRContentLauncherClusterAdditionalInfo new];
                            newElement_4.name = [[NSString alloc] initWithBytes:entry_4.name.data()
                                                                         length:entry_4.name.size()
                                                                       encoding:NSUTF8StringEncoding];
                            newElement_4.value = [[NSString alloc] initWithBytes:entry_4.value.data()
                                                                          length:entry_4.value.size()
                                                                        encoding:NSUTF8StringEncoding];
                            [array_4 addObject:newElement_4];
                        }
                        newElement_1.externalIDList = array_4;
                    }
                } else {
                    newElement_1.externalIDList = nil;
                }
                [array_1 addObject:newElement_1];
            }
            params.search.parameterList = array_1;
        }
        params.autoPlay = [NSNumber numberWithBool:mRequest.autoPlay];
        if (mRequest.data.HasValue()) {
            params.data = [[NSString alloc] initWithBytes:mRequest.data.Value().data()
                                                   length:mRequest.data.Value().size()
                                                 encoding:NSUTF8StringEncoding];
        } else {
            params.data = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster launchContentWithParams:params
                           completionHandler:^(
                               MTRContentLauncherClusterLaunchResponseParams * _Nullable values, NSError * _Nullable error) {
                               NSLog(@"Values: %@", values);
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ContentLauncher::Commands::LaunchContent::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::ContentLauncher::Structs::ContentSearch::Type> mComplex_Search;
};

/*
 * Command LaunchURL
 */
class ContentLauncherLaunchURL : public ClusterCommand {
public:
    ContentLauncherLaunchURL()
        : ClusterCommand("launch-url")
        , mComplex_BrandingInformation(&mRequest.brandingInformation)
    {
        AddArgument("ContentURL", &mRequest.contentURL);
        AddArgument("DisplayString", &mRequest.displayString);
        AddArgument("BrandingInformation", &mComplex_BrandingInformation);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRContentLauncherClusterLaunchURLParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.contentURL = [[NSString alloc] initWithBytes:mRequest.contentURL.data()
                                                     length:mRequest.contentURL.size()
                                                   encoding:NSUTF8StringEncoding];
        if (mRequest.displayString.HasValue()) {
            params.displayString = [[NSString alloc] initWithBytes:mRequest.displayString.Value().data()
                                                            length:mRequest.displayString.Value().size()
                                                          encoding:NSUTF8StringEncoding];
        } else {
            params.displayString = nil;
        }
        if (mRequest.brandingInformation.HasValue()) {
            params.brandingInformation = [MTRContentLauncherClusterBrandingInformation new];
            params.brandingInformation.providerName =
                [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().providerName.data()
                                         length:mRequest.brandingInformation.Value().providerName.size()
                                       encoding:NSUTF8StringEncoding];
            if (mRequest.brandingInformation.Value().background.HasValue()) {
                params.brandingInformation.background = [MTRContentLauncherClusterStyleInformation new];
                if (mRequest.brandingInformation.Value().background.Value().imageUrl.HasValue()) {
                    params.brandingInformation.background.imageUrl = [[NSString alloc]
                        initWithBytes:mRequest.brandingInformation.Value().background.Value().imageUrl.Value().data()
                               length:mRequest.brandingInformation.Value().background.Value().imageUrl.Value().size()
                             encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.background.imageUrl = nil;
                }
                if (mRequest.brandingInformation.Value().background.Value().color.HasValue()) {
                    params.brandingInformation.background.color =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().background.Value().color.Value().data()
                                                 length:mRequest.brandingInformation.Value().background.Value().color.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.background.color = nil;
                }
                if (mRequest.brandingInformation.Value().background.Value().size.HasValue()) {
                    params.brandingInformation.background.size = [MTRContentLauncherClusterDimension new];
                    params.brandingInformation.background.size.width =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().background.Value().size.Value().width];
                    params.brandingInformation.background.size.height =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().background.Value().size.Value().height];
                    params.brandingInformation.background.size.metric = [NSNumber
                        numberWithUnsignedChar:chip::to_underlying(
                                                   mRequest.brandingInformation.Value().background.Value().size.Value().metric)];
                } else {
                    params.brandingInformation.background.size = nil;
                }
            } else {
                params.brandingInformation.background = nil;
            }
            if (mRequest.brandingInformation.Value().logo.HasValue()) {
                params.brandingInformation.logo = [MTRContentLauncherClusterStyleInformation new];
                if (mRequest.brandingInformation.Value().logo.Value().imageUrl.HasValue()) {
                    params.brandingInformation.logo.imageUrl =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().logo.Value().imageUrl.Value().data()
                                                 length:mRequest.brandingInformation.Value().logo.Value().imageUrl.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.logo.imageUrl = nil;
                }
                if (mRequest.brandingInformation.Value().logo.Value().color.HasValue()) {
                    params.brandingInformation.logo.color =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().logo.Value().color.Value().data()
                                                 length:mRequest.brandingInformation.Value().logo.Value().color.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.logo.color = nil;
                }
                if (mRequest.brandingInformation.Value().logo.Value().size.HasValue()) {
                    params.brandingInformation.logo.size = [MTRContentLauncherClusterDimension new];
                    params.brandingInformation.logo.size.width =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().logo.Value().size.Value().width];
                    params.brandingInformation.logo.size.height =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().logo.Value().size.Value().height];
                    params.brandingInformation.logo.size.metric = [NSNumber
                        numberWithUnsignedChar:chip::to_underlying(
                                                   mRequest.brandingInformation.Value().logo.Value().size.Value().metric)];
                } else {
                    params.brandingInformation.logo.size = nil;
                }
            } else {
                params.brandingInformation.logo = nil;
            }
            if (mRequest.brandingInformation.Value().progressBar.HasValue()) {
                params.brandingInformation.progressBar = [MTRContentLauncherClusterStyleInformation new];
                if (mRequest.brandingInformation.Value().progressBar.Value().imageUrl.HasValue()) {
                    params.brandingInformation.progressBar.imageUrl = [[NSString alloc]
                        initWithBytes:mRequest.brandingInformation.Value().progressBar.Value().imageUrl.Value().data()
                               length:mRequest.brandingInformation.Value().progressBar.Value().imageUrl.Value().size()
                             encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.progressBar.imageUrl = nil;
                }
                if (mRequest.brandingInformation.Value().progressBar.Value().color.HasValue()) {
                    params.brandingInformation.progressBar.color = [[NSString alloc]
                        initWithBytes:mRequest.brandingInformation.Value().progressBar.Value().color.Value().data()
                               length:mRequest.brandingInformation.Value().progressBar.Value().color.Value().size()
                             encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.progressBar.color = nil;
                }
                if (mRequest.brandingInformation.Value().progressBar.Value().size.HasValue()) {
                    params.brandingInformation.progressBar.size = [MTRContentLauncherClusterDimension new];
                    params.brandingInformation.progressBar.size.width =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().progressBar.Value().size.Value().width];
                    params.brandingInformation.progressBar.size.height =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().progressBar.Value().size.Value().height];
                    params.brandingInformation.progressBar.size.metric = [NSNumber
                        numberWithUnsignedChar:chip::to_underlying(
                                                   mRequest.brandingInformation.Value().progressBar.Value().size.Value().metric)];
                } else {
                    params.brandingInformation.progressBar.size = nil;
                }
            } else {
                params.brandingInformation.progressBar = nil;
            }
            if (mRequest.brandingInformation.Value().splash.HasValue()) {
                params.brandingInformation.splash = [MTRContentLauncherClusterStyleInformation new];
                if (mRequest.brandingInformation.Value().splash.Value().imageUrl.HasValue()) {
                    params.brandingInformation.splash.imageUrl =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().splash.Value().imageUrl.Value().data()
                                                 length:mRequest.brandingInformation.Value().splash.Value().imageUrl.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.splash.imageUrl = nil;
                }
                if (mRequest.brandingInformation.Value().splash.Value().color.HasValue()) {
                    params.brandingInformation.splash.color =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().splash.Value().color.Value().data()
                                                 length:mRequest.brandingInformation.Value().splash.Value().color.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.splash.color = nil;
                }
                if (mRequest.brandingInformation.Value().splash.Value().size.HasValue()) {
                    params.brandingInformation.splash.size = [MTRContentLauncherClusterDimension new];
                    params.brandingInformation.splash.size.width =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().splash.Value().size.Value().width];
                    params.brandingInformation.splash.size.height =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().splash.Value().size.Value().height];
                    params.brandingInformation.splash.size.metric = [NSNumber
                        numberWithUnsignedChar:chip::to_underlying(
                                                   mRequest.brandingInformation.Value().splash.Value().size.Value().metric)];
                } else {
                    params.brandingInformation.splash.size = nil;
                }
            } else {
                params.brandingInformation.splash = nil;
            }
            if (mRequest.brandingInformation.Value().waterMark.HasValue()) {
                params.brandingInformation.waterMark = [MTRContentLauncherClusterStyleInformation new];
                if (mRequest.brandingInformation.Value().waterMark.Value().imageUrl.HasValue()) {
                    params.brandingInformation.waterMark.imageUrl = [[NSString alloc]
                        initWithBytes:mRequest.brandingInformation.Value().waterMark.Value().imageUrl.Value().data()
                               length:mRequest.brandingInformation.Value().waterMark.Value().imageUrl.Value().size()
                             encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.waterMark.imageUrl = nil;
                }
                if (mRequest.brandingInformation.Value().waterMark.Value().color.HasValue()) {
                    params.brandingInformation.waterMark.color =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().waterMark.Value().color.Value().data()
                                                 length:mRequest.brandingInformation.Value().waterMark.Value().color.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.waterMark.color = nil;
                }
                if (mRequest.brandingInformation.Value().waterMark.Value().size.HasValue()) {
                    params.brandingInformation.waterMark.size = [MTRContentLauncherClusterDimension new];
                    params.brandingInformation.waterMark.size.width =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().waterMark.Value().size.Value().width];
                    params.brandingInformation.waterMark.size.height =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().waterMark.Value().size.Value().height];
                    params.brandingInformation.waterMark.size.metric = [NSNumber
                        numberWithUnsignedChar:chip::to_underlying(
                                                   mRequest.brandingInformation.Value().waterMark.Value().size.Value().metric)];
                } else {
                    params.brandingInformation.waterMark.size = nil;
                }
            } else {
                params.brandingInformation.waterMark = nil;
            }
        } else {
            params.brandingInformation = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                launchURLWithParams:params
                  completionHandler:^(MTRContentLauncherClusterLaunchResponseParams * _Nullable values, NSError * _Nullable error) {
                      NSLog(@"Values: %@", values);
                      responsesNeeded--;
                      if (error != nil) {
                          mError = error;
                          LogNSError("Error", error);
                      }
                      if (responsesNeeded == 0) {
                          SetCommandExitStatus(mError);
                      }
                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ContentLauncher::Commands::LaunchURL::Type mRequest;
    TypedComplexArgument<chip::Optional<chip::app::Clusters::ContentLauncher::Structs::BrandingInformation::Type>>
        mComplex_BrandingInformation;
};

/*
 * Attribute AcceptHeader
 */
class ReadContentLauncherAcceptHeader : public ReadAttribute {
public:
    ReadContentLauncherAcceptHeader()
        : ReadAttribute("accept-header")
    {
    }

    ~ReadContentLauncherAcceptHeader() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptHeaderWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.AcceptHeader response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher AcceptHeader read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherAcceptHeader : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherAcceptHeader()
        : SubscribeAttribute("accept-header")
    {
    }

    ~SubscribeAttributeContentLauncherAcceptHeader() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptHeaderWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.AcceptHeader response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedStreamingProtocols
 */
class ReadContentLauncherSupportedStreamingProtocols : public ReadAttribute {
public:
    ReadContentLauncherSupportedStreamingProtocols()
        : ReadAttribute("supported-streaming-protocols")
    {
    }

    ~ReadContentLauncherSupportedStreamingProtocols() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster
            readAttributeSupportedStreamingProtocolsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.SupportedStreamingProtocols response %@", [value description]);
                if (error != nil) {
                    LogNSError("ContentLauncher SupportedStreamingProtocols read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteContentLauncherSupportedStreamingProtocols : public WriteAttribute {
public:
    WriteContentLauncherSupportedStreamingProtocols()
        : WriteAttribute("supported-streaming-protocols")
    {
        AddArgument("attr-name", "supported-streaming-protocols");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteContentLauncherSupportedStreamingProtocols() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster
            writeAttributeSupportedStreamingProtocolsWithValue:value
                                                        params:params
                                             completionHandler:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("ContentLauncher SupportedStreamingProtocols write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeContentLauncherSupportedStreamingProtocols : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherSupportedStreamingProtocols()
        : SubscribeAttribute("supported-streaming-protocols")
    {
    }

    ~SubscribeAttributeContentLauncherSupportedStreamingProtocols() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeSupportedStreamingProtocolsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.SupportedStreamingProtocols response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadContentLauncherGeneratedCommandList : public ReadAttribute {
public:
    ReadContentLauncherGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadContentLauncherGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeContentLauncherGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadContentLauncherAcceptedCommandList : public ReadAttribute {
public:
    ReadContentLauncherAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadContentLauncherAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeContentLauncherAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadContentLauncherAttributeList : public ReadAttribute {
public:
    ReadContentLauncherAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadContentLauncherAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeContentLauncherAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadContentLauncherFeatureMap : public ReadAttribute {
public:
    ReadContentLauncherFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadContentLauncherFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeContentLauncherFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadContentLauncherClusterRevision : public ReadAttribute {
public:
    ReadContentLauncherClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadContentLauncherClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeContentLauncherClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                               endpoint:endpointId
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster AudioOutput                                                 | 0x050B |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * SelectOutput                                                      |   0x00 |
| * RenameOutput                                                      |   0x01 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * OutputList                                                        | 0x0000 |
| * CurrentOutput                                                     | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command SelectOutput
 */
class AudioOutputSelectOutput : public ClusterCommand {
public:
    AudioOutputSelectOutput()
        : ClusterCommand("select-output")
    {
        AddArgument("Index", 0, UINT8_MAX, &mRequest.index);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint: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
                          completionHandler:^(NSError * _Nullable error) {
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AudioOutput::Commands::SelectOutput::Type mRequest;
};

/*
 * Command RenameOutput
 */
class AudioOutputRenameOutput : public ClusterCommand {
public:
    AudioOutputRenameOutput()
        : ClusterCommand("rename-output")
    {
        AddArgument("Index", 0, UINT8_MAX, &mRequest.index);
        AddArgument("Name", &mRequest.name);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint: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
                          completionHandler:^(NSError * _Nullable error) {
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AudioOutput::Commands::RenameOutput::Type mRequest;
};

/*
 * Attribute OutputList
 */
class ReadAudioOutputOutputList : public ReadAttribute {
public:
    ReadAudioOutputOutputList()
        : ReadAttribute("output-list")
    {
    }

    ~ReadAudioOutputOutputList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeOutputListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.OutputList response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput OutputList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputOutputList : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputOutputList()
        : SubscribeAttribute("output-list")
    {
    }

    ~SubscribeAttributeAudioOutputOutputList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOutputListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.OutputList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentOutput
 */
class ReadAudioOutputCurrentOutput : public ReadAttribute {
public:
    ReadAudioOutputCurrentOutput()
        : ReadAttribute("current-output")
    {
    }

    ~ReadAudioOutputCurrentOutput() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeCurrentOutputWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.CurrentOutput response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput CurrentOutput read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputCurrentOutput : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputCurrentOutput()
        : SubscribeAttribute("current-output")
    {
    }

    ~SubscribeAttributeAudioOutputCurrentOutput() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentOutputWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.CurrentOutput response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadAudioOutputGeneratedCommandList : public ReadAttribute {
public:
    ReadAudioOutputGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadAudioOutputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeAudioOutputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadAudioOutputAcceptedCommandList : public ReadAttribute {
public:
    ReadAudioOutputAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadAudioOutputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeAudioOutputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadAudioOutputAttributeList : public ReadAttribute {
public:
    ReadAudioOutputAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadAudioOutputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeAudioOutputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadAudioOutputFeatureMap : public ReadAttribute {
public:
    ReadAudioOutputFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadAudioOutputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeAudioOutputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadAudioOutputClusterRevision : public ReadAttribute {
public:
    ReadAudioOutputClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadAudioOutputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeAudioOutputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ApplicationLauncher                                         | 0x050C |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * LaunchApp                                                         |   0x00 |
| * StopApp                                                           |   0x01 |
| * HideApp                                                           |   0x02 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * CatalogList                                                       | 0x0000 |
| * CurrentApp                                                        | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command LaunchApp
 */
class ApplicationLauncherLaunchApp : public ClusterCommand {
public:
    ApplicationLauncherLaunchApp()
        : ClusterCommand("launch-app")
        , mComplex_Application(&mRequest.application)
    {
        AddArgument("Application", &mComplex_Application);
        AddArgument("Data", &mRequest.data);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRApplicationLauncherClusterLaunchAppParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.application = [MTRApplicationLauncherClusterApplication new];
        params.application.catalogVendorId = [NSNumber numberWithUnsignedShort:mRequest.application.catalogVendorId];
        params.application.applicationId = [[NSString alloc] initWithBytes:mRequest.application.applicationId.data()
                                                                    length:mRequest.application.applicationId.size()
                                                                  encoding:NSUTF8StringEncoding];
        if (mRequest.data.HasValue()) {
            params.data = [NSData dataWithBytes:mRequest.data.Value().data() length:mRequest.data.Value().size()];
        } else {
            params.data = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster launchAppWithParams:params
                       completionHandler:^(
                           MTRApplicationLauncherClusterLauncherResponseParams * _Nullable values, NSError * _Nullable error) {
                           NSLog(@"Values: %@", values);
                           responsesNeeded--;
                           if (error != nil) {
                               mError = error;
                               LogNSError("Error", error);
                           }
                           if (responsesNeeded == 0) {
                               SetCommandExitStatus(mError);
                           }
                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ApplicationLauncher::Commands::LaunchApp::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::ApplicationLauncher::Structs::Application::Type> mComplex_Application;
};

/*
 * Command StopApp
 */
class ApplicationLauncherStopApp : public ClusterCommand {
public:
    ApplicationLauncherStopApp()
        : ClusterCommand("stop-app")
        , mComplex_Application(&mRequest.application)
    {
        AddArgument("Application", &mComplex_Application);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRApplicationLauncherClusterStopAppParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.application = [MTRApplicationLauncherClusterApplication new];
        params.application.catalogVendorId = [NSNumber numberWithUnsignedShort:mRequest.application.catalogVendorId];
        params.application.applicationId = [[NSString alloc] initWithBytes:mRequest.application.applicationId.data()
                                                                    length:mRequest.application.applicationId.size()
                                                                  encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stopAppWithParams:params
                     completionHandler:^(
                         MTRApplicationLauncherClusterLauncherResponseParams * _Nullable values, NSError * _Nullable error) {
                         NSLog(@"Values: %@", values);
                         responsesNeeded--;
                         if (error != nil) {
                             mError = error;
                             LogNSError("Error", error);
                         }
                         if (responsesNeeded == 0) {
                             SetCommandExitStatus(mError);
                         }
                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ApplicationLauncher::Commands::StopApp::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::ApplicationLauncher::Structs::Application::Type> mComplex_Application;
};

/*
 * Command HideApp
 */
class ApplicationLauncherHideApp : public ClusterCommand {
public:
    ApplicationLauncherHideApp()
        : ClusterCommand("hide-app")
        , mComplex_Application(&mRequest.application)
    {
        AddArgument("Application", &mComplex_Application);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRApplicationLauncherClusterHideAppParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.application = [MTRApplicationLauncherClusterApplication new];
        params.application.catalogVendorId = [NSNumber numberWithUnsignedShort:mRequest.application.catalogVendorId];
        params.application.applicationId = [[NSString alloc] initWithBytes:mRequest.application.applicationId.data()
                                                                    length:mRequest.application.applicationId.size()
                                                                  encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster hideAppWithParams:params
                     completionHandler:^(
                         MTRApplicationLauncherClusterLauncherResponseParams * _Nullable values, NSError * _Nullable error) {
                         NSLog(@"Values: %@", values);
                         responsesNeeded--;
                         if (error != nil) {
                             mError = error;
                             LogNSError("Error", error);
                         }
                         if (responsesNeeded == 0) {
                             SetCommandExitStatus(mError);
                         }
                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ApplicationLauncher::Commands::HideApp::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::ApplicationLauncher::Structs::Application::Type> mComplex_Application;
};

/*
 * Attribute CatalogList
 */
class ReadApplicationLauncherCatalogList : public ReadAttribute {
public:
    ReadApplicationLauncherCatalogList()
        : ReadAttribute("catalog-list")
    {
    }

    ~ReadApplicationLauncherCatalogList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeCatalogListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.CatalogList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher CatalogList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherCatalogList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherCatalogList()
        : SubscribeAttribute("catalog-list")
    {
    }

    ~SubscribeAttributeApplicationLauncherCatalogList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCatalogListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.CatalogList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentApp
 */
class ReadApplicationLauncherCurrentApp : public ReadAttribute {
public:
    ReadApplicationLauncherCurrentApp()
        : ReadAttribute("current-app")
    {
    }

    ~ReadApplicationLauncherCurrentApp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeCurrentAppWithCompletionHandler:^(
            MTRApplicationLauncherClusterApplicationEP * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.CurrentApp response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher CurrentApp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteApplicationLauncherCurrentApp : public WriteAttribute {
public:
    WriteApplicationLauncherCurrentApp()
        : WriteAttribute("current-app")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "current-app");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteApplicationLauncherCurrentApp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        MTRApplicationLauncherClusterApplicationEP * _Nullable value;
        if (mValue.IsNull()) {
            value = nil;
        } else {
            value = [MTRApplicationLauncherClusterApplicationEP new];
            value.application = [MTRApplicationLauncherClusterApplication new];
            value.application.catalogVendorId = [NSNumber numberWithUnsignedShort:mValue.Value().application.catalogVendorId];
            value.application.applicationId = [[NSString alloc] initWithBytes:mValue.Value().application.applicationId.data()
                                                                       length:mValue.Value().application.applicationId.size()
                                                                     encoding:NSUTF8StringEncoding];
            if (mValue.Value().endpoint.HasValue()) {
                value.endpoint = [NSNumber numberWithUnsignedShort:mValue.Value().endpoint.Value()];
            } else {
                value.endpoint = nil;
            }
        }

        [cluster writeAttributeCurrentAppWithValue:value
                                            params:params
                                 completionHandler:^(NSError * _Nullable error) {
                                     if (error != nil) {
                                         LogNSError("ApplicationLauncher CurrentApp write Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::Nullable<chip::app::Clusters::ApplicationLauncher::Structs::ApplicationEP::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::Nullable<chip::app::Clusters::ApplicationLauncher::Structs::ApplicationEP::Type>>
        mComplex;
};

class SubscribeAttributeApplicationLauncherCurrentApp : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherCurrentApp()
        : SubscribeAttribute("current-app")
    {
    }

    ~SubscribeAttributeApplicationLauncherCurrentApp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentAppWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRApplicationLauncherClusterApplicationEP * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.CurrentApp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadApplicationLauncherGeneratedCommandList : public ReadAttribute {
public:
    ReadApplicationLauncherGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadApplicationLauncherGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeApplicationLauncherGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadApplicationLauncherAcceptedCommandList : public ReadAttribute {
public:
    ReadApplicationLauncherAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadApplicationLauncherAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeApplicationLauncherAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadApplicationLauncherAttributeList : public ReadAttribute {
public:
    ReadApplicationLauncherAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadApplicationLauncherAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeApplicationLauncherAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadApplicationLauncherFeatureMap : public ReadAttribute {
public:
    ReadApplicationLauncherFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadApplicationLauncherFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeApplicationLauncherFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadApplicationLauncherClusterRevision : public ReadAttribute {
public:
    ReadApplicationLauncherClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadApplicationLauncherClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeApplicationLauncherClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                       endpoint:endpointId
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ApplicationBasic                                            | 0x050D |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * VendorName                                                        | 0x0000 |
| * VendorID                                                          | 0x0001 |
| * ApplicationName                                                   | 0x0002 |
| * ProductID                                                         | 0x0003 |
| * Application                                                       | 0x0004 |
| * Status                                                            | 0x0005 |
| * ApplicationVersion                                                | 0x0006 |
| * AllowedVendorList                                                 | 0x0007 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute VendorName
 */
class ReadApplicationBasicVendorName : public ReadAttribute {
public:
    ReadApplicationBasicVendorName()
        : ReadAttribute("vendor-name")
    {
    }

    ~ReadApplicationBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeVendorNameWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.VendorName response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic VendorName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicVendorName : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicVendorName()
        : SubscribeAttribute("vendor-name")
    {
    }

    ~SubscribeAttributeApplicationBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeVendorNameWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.VendorName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorID
 */
class ReadApplicationBasicVendorID : public ReadAttribute {
public:
    ReadApplicationBasicVendorID()
        : ReadAttribute("vendor-id")
    {
    }

    ~ReadApplicationBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeVendorIDWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.VendorID response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic VendorID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicVendorID : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicVendorID()
        : SubscribeAttribute("vendor-id")
    {
    }

    ~SubscribeAttributeApplicationBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeVendorIDWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.VendorID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApplicationName
 */
class ReadApplicationBasicApplicationName : public ReadAttribute {
public:
    ReadApplicationBasicApplicationName()
        : ReadAttribute("application-name")
    {
    }

    ~ReadApplicationBasicApplicationName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeApplicationNameWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.ApplicationName response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic ApplicationName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicApplicationName : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicApplicationName()
        : SubscribeAttribute("application-name")
    {
    }

    ~SubscribeAttributeApplicationBasicApplicationName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeApplicationNameWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.ApplicationName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductID
 */
class ReadApplicationBasicProductID : public ReadAttribute {
public:
    ReadApplicationBasicProductID()
        : ReadAttribute("product-id")
    {
    }

    ~ReadApplicationBasicProductID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeProductIDWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.ProductID response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic ProductID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicProductID : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicProductID()
        : SubscribeAttribute("product-id")
    {
    }

    ~SubscribeAttributeApplicationBasicProductID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeProductIDWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.ProductID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Application
 */
class ReadApplicationBasicApplication : public ReadAttribute {
public:
    ReadApplicationBasicApplication()
        : ReadAttribute("application")
    {
    }

    ~ReadApplicationBasicApplication() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeApplicationWithCompletionHandler:^(
            MTRApplicationBasicClusterApplicationBasicApplication * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.Application response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic Application read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicApplication : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicApplication()
        : SubscribeAttribute("application")
    {
    }

    ~SubscribeAttributeApplicationBasicApplication() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeApplicationWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRApplicationBasicClusterApplicationBasicApplication * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.Application response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Status
 */
class ReadApplicationBasicStatus : public ReadAttribute {
public:
    ReadApplicationBasicStatus()
        : ReadAttribute("status")
    {
    }

    ~ReadApplicationBasicStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeStatusWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.Status response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic Status read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicStatus : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicStatus()
        : SubscribeAttribute("status")
    {
    }

    ~SubscribeAttributeApplicationBasicStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeStatusWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.Status response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApplicationVersion
 */
class ReadApplicationBasicApplicationVersion : public ReadAttribute {
public:
    ReadApplicationBasicApplicationVersion()
        : ReadAttribute("application-version")
    {
    }

    ~ReadApplicationBasicApplicationVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeApplicationVersionWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.ApplicationVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic ApplicationVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicApplicationVersion : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicApplicationVersion()
        : SubscribeAttribute("application-version")
    {
    }

    ~SubscribeAttributeApplicationBasicApplicationVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeApplicationVersionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.ApplicationVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AllowedVendorList
 */
class ReadApplicationBasicAllowedVendorList : public ReadAttribute {
public:
    ReadApplicationBasicAllowedVendorList()
        : ReadAttribute("allowed-vendor-list")
    {
    }

    ~ReadApplicationBasicAllowedVendorList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAllowedVendorListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.AllowedVendorList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic AllowedVendorList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicAllowedVendorList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicAllowedVendorList()
        : SubscribeAttribute("allowed-vendor-list")
    {
    }

    ~SubscribeAttributeApplicationBasicAllowedVendorList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAllowedVendorListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.AllowedVendorList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadApplicationBasicGeneratedCommandList : public ReadAttribute {
public:
    ReadApplicationBasicGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadApplicationBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeApplicationBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadApplicationBasicAcceptedCommandList : public ReadAttribute {
public:
    ReadApplicationBasicAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadApplicationBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeApplicationBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadApplicationBasicAttributeList : public ReadAttribute {
public:
    ReadApplicationBasicAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadApplicationBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeApplicationBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadApplicationBasicFeatureMap : public ReadAttribute {
public:
    ReadApplicationBasicFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadApplicationBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeApplicationBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadApplicationBasicClusterRevision : public ReadAttribute {
public:
    ReadApplicationBasicClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadApplicationBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeApplicationBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                                 endpoint:endpointId
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster AccountLogin                                                | 0x050E |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * GetSetupPIN                                                       |   0x00 |
| * Login                                                             |   0x02 |
| * Logout                                                            |   0x03 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command GetSetupPIN
 */
class AccountLoginGetSetupPIN : public ClusterCommand {
public:
    AccountLoginGetSetupPIN()
        : ClusterCommand("get-setup-pin")
    {
        AddArgument("TempAccountIdentifier", &mRequest.tempAccountIdentifier);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint: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
                         completionHandler:^(
                             MTRAccountLoginClusterGetSetupPINResponseParams * _Nullable values, NSError * _Nullable error) {
                             NSLog(@"Values: %@", values);
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AccountLogin::Commands::GetSetupPIN::Type mRequest;
};

/*
 * Command Login
 */
class AccountLoginLogin : public ClusterCommand {
public:
    AccountLoginLogin()
        : ClusterCommand("login")
    {
        AddArgument("TempAccountIdentifier", &mRequest.tempAccountIdentifier);
        AddArgument("SetupPIN", &mRequest.setupPIN);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint: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
                   completionHandler:^(NSError * _Nullable error) {
                       responsesNeeded--;
                       if (error != nil) {
                           mError = error;
                           LogNSError("Error", error);
                       }
                       if (responsesNeeded == 0) {
                           SetCommandExitStatus(mError);
                       }
                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AccountLogin::Commands::Login::Type mRequest;
};

/*
 * Command Logout
 */
class AccountLoginLogout : public ClusterCommand {
public:
    AccountLoginLogout()
        : ClusterCommand("logout")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint: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
                    completionHandler:^(NSError * _Nullable error) {
                        responsesNeeded--;
                        if (error != nil) {
                            mError = error;
                            LogNSError("Error", error);
                        }
                        if (responsesNeeded == 0) {
                            SetCommandExitStatus(mError);
                        }
                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute GeneratedCommandList
 */
class ReadAccountLoginGeneratedCommandList : public ReadAttribute {
public:
    ReadAccountLoginGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadAccountLoginGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeAccountLoginGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadAccountLoginAcceptedCommandList : public ReadAttribute {
public:
    ReadAccountLoginAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadAccountLoginAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeAccountLoginAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadAccountLoginAttributeList : public ReadAttribute {
public:
    ReadAccountLoginAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadAccountLoginAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeAccountLoginAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadAccountLoginFeatureMap : public ReadAttribute {
public:
    ReadAccountLoginFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadAccountLoginFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeAccountLoginFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadAccountLoginClusterRevision : public ReadAttribute {
public:
    ReadAccountLoginClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadAccountLoginClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeAccountLoginClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                         endpoint:endpointId
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ElectricalMeasurement                                       | 0x0B04 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * GetProfileInfoCommand                                             |   0x00 |
| * GetMeasurementProfileCommand                                      |   0x01 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasurementType                                                   | 0x0000 |
| * DcVoltage                                                         | 0x0100 |
| * DcVoltageMin                                                      | 0x0101 |
| * DcVoltageMax                                                      | 0x0102 |
| * DcCurrent                                                         | 0x0103 |
| * DcCurrentMin                                                      | 0x0104 |
| * DcCurrentMax                                                      | 0x0105 |
| * DcPower                                                           | 0x0106 |
| * DcPowerMin                                                        | 0x0107 |
| * DcPowerMax                                                        | 0x0108 |
| * DcVoltageMultiplier                                               | 0x0200 |
| * DcVoltageDivisor                                                  | 0x0201 |
| * DcCurrentMultiplier                                               | 0x0202 |
| * DcCurrentDivisor                                                  | 0x0203 |
| * DcPowerMultiplier                                                 | 0x0204 |
| * DcPowerDivisor                                                    | 0x0205 |
| * AcFrequency                                                       | 0x0300 |
| * AcFrequencyMin                                                    | 0x0301 |
| * AcFrequencyMax                                                    | 0x0302 |
| * NeutralCurrent                                                    | 0x0303 |
| * TotalActivePower                                                  | 0x0304 |
| * TotalReactivePower                                                | 0x0305 |
| * TotalApparentPower                                                | 0x0306 |
| * Measured1stHarmonicCurrent                                        | 0x0307 |
| * Measured3rdHarmonicCurrent                                        | 0x0308 |
| * Measured5thHarmonicCurrent                                        | 0x0309 |
| * Measured7thHarmonicCurrent                                        | 0x030A |
| * Measured9thHarmonicCurrent                                        | 0x030B |
| * Measured11thHarmonicCurrent                                       | 0x030C |
| * MeasuredPhase1stHarmonicCurrent                                   | 0x030D |
| * MeasuredPhase3rdHarmonicCurrent                                   | 0x030E |
| * MeasuredPhase5thHarmonicCurrent                                   | 0x030F |
| * MeasuredPhase7thHarmonicCurrent                                   | 0x0310 |
| * MeasuredPhase9thHarmonicCurrent                                   | 0x0311 |
| * MeasuredPhase11thHarmonicCurrent                                  | 0x0312 |
| * AcFrequencyMultiplier                                             | 0x0400 |
| * AcFrequencyDivisor                                                | 0x0401 |
| * PowerMultiplier                                                   | 0x0402 |
| * PowerDivisor                                                      | 0x0403 |
| * HarmonicCurrentMultiplier                                         | 0x0404 |
| * PhaseHarmonicCurrentMultiplier                                    | 0x0405 |
| * InstantaneousVoltage                                              | 0x0500 |
| * InstantaneousLineCurrent                                          | 0x0501 |
| * InstantaneousActiveCurrent                                        | 0x0502 |
| * InstantaneousReactiveCurrent                                      | 0x0503 |
| * InstantaneousPower                                                | 0x0504 |
| * RmsVoltage                                                        | 0x0505 |
| * RmsVoltageMin                                                     | 0x0506 |
| * RmsVoltageMax                                                     | 0x0507 |
| * RmsCurrent                                                        | 0x0508 |
| * RmsCurrentMin                                                     | 0x0509 |
| * RmsCurrentMax                                                     | 0x050A |
| * ActivePower                                                       | 0x050B |
| * ActivePowerMin                                                    | 0x050C |
| * ActivePowerMax                                                    | 0x050D |
| * ReactivePower                                                     | 0x050E |
| * ApparentPower                                                     | 0x050F |
| * PowerFactor                                                       | 0x0510 |
| * AverageRmsVoltageMeasurementPeriod                                | 0x0511 |
| * AverageRmsUnderVoltageCounter                                     | 0x0513 |
| * RmsExtremeOverVoltagePeriod                                       | 0x0514 |
| * RmsExtremeUnderVoltagePeriod                                      | 0x0515 |
| * RmsVoltageSagPeriod                                               | 0x0516 |
| * RmsVoltageSwellPeriod                                             | 0x0517 |
| * AcVoltageMultiplier                                               | 0x0600 |
| * AcVoltageDivisor                                                  | 0x0601 |
| * AcCurrentMultiplier                                               | 0x0602 |
| * AcCurrentDivisor                                                  | 0x0603 |
| * AcPowerMultiplier                                                 | 0x0604 |
| * AcPowerDivisor                                                    | 0x0605 |
| * OverloadAlarmsMask                                                | 0x0700 |
| * VoltageOverload                                                   | 0x0701 |
| * CurrentOverload                                                   | 0x0702 |
| * AcOverloadAlarmsMask                                              | 0x0800 |
| * AcVoltageOverload                                                 | 0x0801 |
| * AcCurrentOverload                                                 | 0x0802 |
| * AcActivePowerOverload                                             | 0x0803 |
| * AcReactivePowerOverload                                           | 0x0804 |
| * AverageRmsOverVoltage                                             | 0x0805 |
| * AverageRmsUnderVoltage                                            | 0x0806 |
| * RmsExtremeOverVoltage                                             | 0x0807 |
| * RmsExtremeUnderVoltage                                            | 0x0808 |
| * RmsVoltageSag                                                     | 0x0809 |
| * RmsVoltageSwell                                                   | 0x080A |
| * LineCurrentPhaseB                                                 | 0x0901 |
| * ActiveCurrentPhaseB                                               | 0x0902 |
| * ReactiveCurrentPhaseB                                             | 0x0903 |
| * RmsVoltagePhaseB                                                  | 0x0905 |
| * RmsVoltageMinPhaseB                                               | 0x0906 |
| * RmsVoltageMaxPhaseB                                               | 0x0907 |
| * RmsCurrentPhaseB                                                  | 0x0908 |
| * RmsCurrentMinPhaseB                                               | 0x0909 |
| * RmsCurrentMaxPhaseB                                               | 0x090A |
| * ActivePowerPhaseB                                                 | 0x090B |
| * ActivePowerMinPhaseB                                              | 0x090C |
| * ActivePowerMaxPhaseB                                              | 0x090D |
| * ReactivePowerPhaseB                                               | 0x090E |
| * ApparentPowerPhaseB                                               | 0x090F |
| * PowerFactorPhaseB                                                 | 0x0910 |
| * AverageRmsVoltageMeasurementPeriodPhaseB                          | 0x0911 |
| * AverageRmsOverVoltageCounterPhaseB                                | 0x0912 |
| * AverageRmsUnderVoltageCounterPhaseB                               | 0x0913 |
| * RmsExtremeOverVoltagePeriodPhaseB                                 | 0x0914 |
| * RmsExtremeUnderVoltagePeriodPhaseB                                | 0x0915 |
| * RmsVoltageSagPeriodPhaseB                                         | 0x0916 |
| * RmsVoltageSwellPeriodPhaseB                                       | 0x0917 |
| * LineCurrentPhaseC                                                 | 0x0A01 |
| * ActiveCurrentPhaseC                                               | 0x0A02 |
| * ReactiveCurrentPhaseC                                             | 0x0A03 |
| * RmsVoltagePhaseC                                                  | 0x0A05 |
| * RmsVoltageMinPhaseC                                               | 0x0A06 |
| * RmsVoltageMaxPhaseC                                               | 0x0A07 |
| * RmsCurrentPhaseC                                                  | 0x0A08 |
| * RmsCurrentMinPhaseC                                               | 0x0A09 |
| * RmsCurrentMaxPhaseC                                               | 0x0A0A |
| * ActivePowerPhaseC                                                 | 0x0A0B |
| * ActivePowerMinPhaseC                                              | 0x0A0C |
| * ActivePowerMaxPhaseC                                              | 0x0A0D |
| * ReactivePowerPhaseC                                               | 0x0A0E |
| * ApparentPowerPhaseC                                               | 0x0A0F |
| * PowerFactorPhaseC                                                 | 0x0A10 |
| * AverageRmsVoltageMeasurementPeriodPhaseC                          | 0x0A11 |
| * AverageRmsOverVoltageCounterPhaseC                                | 0x0A12 |
| * AverageRmsUnderVoltageCounterPhaseC                               | 0x0A13 |
| * RmsExtremeOverVoltagePeriodPhaseC                                 | 0x0A14 |
| * RmsExtremeUnderVoltagePeriodPhaseC                                | 0x0A15 |
| * RmsVoltageSagPeriodPhaseC                                         | 0x0A16 |
| * RmsVoltageSwellPeriodPhaseC                                       | 0x0A17 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command GetProfileInfoCommand
 */
class ElectricalMeasurementGetProfileInfoCommand : public ClusterCommand {
public:
    ElectricalMeasurementGetProfileInfoCommand()
        : ClusterCommand("get-profile-info-command")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint: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
                                   completionHandler:^(NSError * _Nullable error) {
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command GetMeasurementProfileCommand
 */
class ElectricalMeasurementGetMeasurementProfileCommand : public ClusterCommand {
public:
    ElectricalMeasurementGetMeasurementProfileCommand()
        : ClusterCommand("get-measurement-profile-command")
    {
        AddArgument("AttributeId", 0, UINT16_MAX, &mRequest.attributeId);
        AddArgument("StartTime", 0, UINT32_MAX, &mRequest.startTime);
        AddArgument("NumberOfIntervals", 0, UINT8_MAX, &mRequest.numberOfIntervals);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint: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
                                          completionHandler:^(NSError * _Nullable error) {
                                              responsesNeeded--;
                                              if (error != nil) {
                                                  mError = error;
                                                  LogNSError("Error", error);
                                              }
                                              if (responsesNeeded == 0) {
                                                  SetCommandExitStatus(mError);
                                              }
                                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ElectricalMeasurement::Commands::GetMeasurementProfileCommand::Type mRequest;
};

/*
 * Attribute MeasurementType
 */
class ReadElectricalMeasurementMeasurementType : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasurementType()
        : ReadAttribute("measurement-type")
    {
    }

    ~ReadElectricalMeasurementMeasurementType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasurementTypeWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.MeasurementType response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement MeasurementType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasurementType : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasurementType()
        : SubscribeAttribute("measurement-type")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasurementType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasurementTypeWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasurementType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcVoltage
 */
class ReadElectricalMeasurementDcVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementDcVoltage()
        : ReadAttribute("dc-voltage")
    {
    }

    ~ReadElectricalMeasurementDcVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000100) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcVoltageWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcVoltage()
        : SubscribeAttribute("dc-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000100) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcVoltageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcVoltageMin
 */
class ReadElectricalMeasurementDcVoltageMin : public ReadAttribute {
public:
    ReadElectricalMeasurementDcVoltageMin()
        : ReadAttribute("dc-voltage-min")
    {
    }

    ~ReadElectricalMeasurementDcVoltageMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000101) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcVoltageMinWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcVoltageMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcVoltageMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcVoltageMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcVoltageMin()
        : SubscribeAttribute("dc-voltage-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcVoltageMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000101) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcVoltageMinWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcVoltageMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcVoltageMax
 */
class ReadElectricalMeasurementDcVoltageMax : public ReadAttribute {
public:
    ReadElectricalMeasurementDcVoltageMax()
        : ReadAttribute("dc-voltage-max")
    {
    }

    ~ReadElectricalMeasurementDcVoltageMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000102) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcVoltageMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcVoltageMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcVoltageMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcVoltageMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcVoltageMax()
        : SubscribeAttribute("dc-voltage-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcVoltageMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000102) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcVoltageMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcVoltageMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcCurrent
 */
class ReadElectricalMeasurementDcCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementDcCurrent()
        : ReadAttribute("dc-current")
    {
    }

    ~ReadElectricalMeasurementDcCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000103) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcCurrent()
        : SubscribeAttribute("dc-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000103) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcCurrentMin
 */
class ReadElectricalMeasurementDcCurrentMin : public ReadAttribute {
public:
    ReadElectricalMeasurementDcCurrentMin()
        : ReadAttribute("dc-current-min")
    {
    }

    ~ReadElectricalMeasurementDcCurrentMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000104) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcCurrentMinWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcCurrentMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcCurrentMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcCurrentMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcCurrentMin()
        : SubscribeAttribute("dc-current-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcCurrentMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000104) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcCurrentMinWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcCurrentMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcCurrentMax
 */
class ReadElectricalMeasurementDcCurrentMax : public ReadAttribute {
public:
    ReadElectricalMeasurementDcCurrentMax()
        : ReadAttribute("dc-current-max")
    {
    }

    ~ReadElectricalMeasurementDcCurrentMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000105) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcCurrentMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcCurrentMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcCurrentMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcCurrentMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcCurrentMax()
        : SubscribeAttribute("dc-current-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcCurrentMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000105) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcCurrentMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcCurrentMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcPower
 */
class ReadElectricalMeasurementDcPower : public ReadAttribute {
public:
    ReadElectricalMeasurementDcPower()
        : ReadAttribute("dc-power")
    {
    }

    ~ReadElectricalMeasurementDcPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000106) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcPowerWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcPower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcPower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcPower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcPower()
        : SubscribeAttribute("dc-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000106) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcPowerWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcPower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcPowerMin
 */
class ReadElectricalMeasurementDcPowerMin : public ReadAttribute {
public:
    ReadElectricalMeasurementDcPowerMin()
        : ReadAttribute("dc-power-min")
    {
    }

    ~ReadElectricalMeasurementDcPowerMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000107) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcPowerMinWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcPowerMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcPowerMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcPowerMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcPowerMin()
        : SubscribeAttribute("dc-power-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcPowerMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000107) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcPowerMinWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcPowerMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcPowerMax
 */
class ReadElectricalMeasurementDcPowerMax : public ReadAttribute {
public:
    ReadElectricalMeasurementDcPowerMax()
        : ReadAttribute("dc-power-max")
    {
    }

    ~ReadElectricalMeasurementDcPowerMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000108) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcPowerMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcPowerMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcPowerMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcPowerMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcPowerMax()
        : SubscribeAttribute("dc-power-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcPowerMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000108) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcPowerMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcPowerMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcVoltageMultiplier
 */
class ReadElectricalMeasurementDcVoltageMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementDcVoltageMultiplier()
        : ReadAttribute("dc-voltage-multiplier")
    {
    }

    ~ReadElectricalMeasurementDcVoltageMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000200) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcVoltageMultiplierWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcVoltageMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcVoltageMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcVoltageMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcVoltageMultiplier()
        : SubscribeAttribute("dc-voltage-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcVoltageMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000200) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcVoltageMultiplierWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcVoltageMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcVoltageDivisor
 */
class ReadElectricalMeasurementDcVoltageDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementDcVoltageDivisor()
        : ReadAttribute("dc-voltage-divisor")
    {
    }

    ~ReadElectricalMeasurementDcVoltageDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000201) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcVoltageDivisorWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcVoltageDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcVoltageDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcVoltageDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcVoltageDivisor()
        : SubscribeAttribute("dc-voltage-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcVoltageDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000201) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcVoltageDivisorWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcVoltageDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcCurrentMultiplier
 */
class ReadElectricalMeasurementDcCurrentMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementDcCurrentMultiplier()
        : ReadAttribute("dc-current-multiplier")
    {
    }

    ~ReadElectricalMeasurementDcCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000202) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcCurrentMultiplierWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcCurrentMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcCurrentMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcCurrentMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcCurrentMultiplier()
        : SubscribeAttribute("dc-current-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000202) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcCurrentMultiplierWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcCurrentMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcCurrentDivisor
 */
class ReadElectricalMeasurementDcCurrentDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementDcCurrentDivisor()
        : ReadAttribute("dc-current-divisor")
    {
    }

    ~ReadElectricalMeasurementDcCurrentDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000203) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcCurrentDivisorWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcCurrentDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcCurrentDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcCurrentDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcCurrentDivisor()
        : SubscribeAttribute("dc-current-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcCurrentDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000203) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcCurrentDivisorWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcCurrentDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcPowerMultiplier
 */
class ReadElectricalMeasurementDcPowerMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementDcPowerMultiplier()
        : ReadAttribute("dc-power-multiplier")
    {
    }

    ~ReadElectricalMeasurementDcPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000204) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcPowerMultiplierWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcPowerMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcPowerMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcPowerMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcPowerMultiplier()
        : SubscribeAttribute("dc-power-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000204) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcPowerMultiplierWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcPowerMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcPowerDivisor
 */
class ReadElectricalMeasurementDcPowerDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementDcPowerDivisor()
        : ReadAttribute("dc-power-divisor")
    {
    }

    ~ReadElectricalMeasurementDcPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000205) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcPowerDivisorWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcPowerDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcPowerDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcPowerDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcPowerDivisor()
        : SubscribeAttribute("dc-power-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000205) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeDcPowerDivisorWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcPowerDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcFrequency
 */
class ReadElectricalMeasurementAcFrequency : public ReadAttribute {
public:
    ReadElectricalMeasurementAcFrequency()
        : ReadAttribute("ac-frequency")
    {
    }

    ~ReadElectricalMeasurementAcFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000300) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcFrequencyWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcFrequency response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcFrequency read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcFrequency : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcFrequency()
        : SubscribeAttribute("ac-frequency")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000300) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcFrequencyWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcFrequency response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcFrequencyMin
 */
class ReadElectricalMeasurementAcFrequencyMin : public ReadAttribute {
public:
    ReadElectricalMeasurementAcFrequencyMin()
        : ReadAttribute("ac-frequency-min")
    {
    }

    ~ReadElectricalMeasurementAcFrequencyMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000301) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcFrequencyMinWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcFrequencyMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcFrequencyMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcFrequencyMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcFrequencyMin()
        : SubscribeAttribute("ac-frequency-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcFrequencyMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000301) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcFrequencyMinWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcFrequencyMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcFrequencyMax
 */
class ReadElectricalMeasurementAcFrequencyMax : public ReadAttribute {
public:
    ReadElectricalMeasurementAcFrequencyMax()
        : ReadAttribute("ac-frequency-max")
    {
    }

    ~ReadElectricalMeasurementAcFrequencyMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000302) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcFrequencyMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcFrequencyMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcFrequencyMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcFrequencyMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcFrequencyMax()
        : SubscribeAttribute("ac-frequency-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcFrequencyMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000302) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcFrequencyMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcFrequencyMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NeutralCurrent
 */
class ReadElectricalMeasurementNeutralCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementNeutralCurrent()
        : ReadAttribute("neutral-current")
    {
    }

    ~ReadElectricalMeasurementNeutralCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000303) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeNeutralCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.NeutralCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement NeutralCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementNeutralCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementNeutralCurrent()
        : SubscribeAttribute("neutral-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementNeutralCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000303) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNeutralCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.NeutralCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TotalActivePower
 */
class ReadElectricalMeasurementTotalActivePower : public ReadAttribute {
public:
    ReadElectricalMeasurementTotalActivePower()
        : ReadAttribute("total-active-power")
    {
    }

    ~ReadElectricalMeasurementTotalActivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000304) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeTotalActivePowerWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.TotalActivePower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement TotalActivePower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementTotalActivePower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementTotalActivePower()
        : SubscribeAttribute("total-active-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementTotalActivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000304) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTotalActivePowerWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.TotalActivePower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TotalReactivePower
 */
class ReadElectricalMeasurementTotalReactivePower : public ReadAttribute {
public:
    ReadElectricalMeasurementTotalReactivePower()
        : ReadAttribute("total-reactive-power")
    {
    }

    ~ReadElectricalMeasurementTotalReactivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000305) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeTotalReactivePowerWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.TotalReactivePower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement TotalReactivePower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementTotalReactivePower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementTotalReactivePower()
        : SubscribeAttribute("total-reactive-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementTotalReactivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000305) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTotalReactivePowerWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.TotalReactivePower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TotalApparentPower
 */
class ReadElectricalMeasurementTotalApparentPower : public ReadAttribute {
public:
    ReadElectricalMeasurementTotalApparentPower()
        : ReadAttribute("total-apparent-power")
    {
    }

    ~ReadElectricalMeasurementTotalApparentPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000306) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeTotalApparentPowerWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.TotalApparentPower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement TotalApparentPower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementTotalApparentPower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementTotalApparentPower()
        : SubscribeAttribute("total-apparent-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementTotalApparentPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000306) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTotalApparentPowerWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.TotalApparentPower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured1stHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured1stHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured1stHarmonicCurrent()
        : ReadAttribute("measured1st-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured1stHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000307) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasured1stHarmonicCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured1stHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement Measured1stHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured1stHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured1stHarmonicCurrent()
        : SubscribeAttribute("measured1st-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured1stHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000307) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasured1stHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured1stHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured3rdHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured3rdHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured3rdHarmonicCurrent()
        : ReadAttribute("measured3rd-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured3rdHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000308) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasured3rdHarmonicCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured3rdHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement Measured3rdHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured3rdHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured3rdHarmonicCurrent()
        : SubscribeAttribute("measured3rd-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured3rdHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000308) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasured3rdHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured3rdHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured5thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured5thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured5thHarmonicCurrent()
        : ReadAttribute("measured5th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured5thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000309) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasured5thHarmonicCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured5thHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement Measured5thHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured5thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured5thHarmonicCurrent()
        : SubscribeAttribute("measured5th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured5thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000309) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasured5thHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured5thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured7thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured7thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured7thHarmonicCurrent()
        : ReadAttribute("measured7th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured7thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasured7thHarmonicCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured7thHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement Measured7thHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured7thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured7thHarmonicCurrent()
        : SubscribeAttribute("measured7th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured7thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasured7thHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured7thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured9thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured9thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured9thHarmonicCurrent()
        : ReadAttribute("measured9th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured9thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasured9thHarmonicCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured9thHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement Measured9thHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured9thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured9thHarmonicCurrent()
        : SubscribeAttribute("measured9th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured9thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasured9thHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured9thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured11thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured11thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured11thHarmonicCurrent()
        : ReadAttribute("measured11th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured11thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasured11thHarmonicCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured11thHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement Measured11thHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured11thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured11thHarmonicCurrent()
        : SubscribeAttribute("measured11th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured11thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasured11thHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured11thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase1stHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase1stHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase1stHarmonicCurrent()
        : ReadAttribute("measured-phase1st-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase1stHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasuredPhase1stHarmonicCurrentWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.MeasuredPhase1stHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement MeasuredPhase1stHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase1stHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase1stHarmonicCurrent()
        : SubscribeAttribute("measured-phase1st-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase1stHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredPhase1stHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase1stHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase3rdHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase3rdHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase3rdHarmonicCurrent()
        : ReadAttribute("measured-phase3rd-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase3rdHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasuredPhase3rdHarmonicCurrentWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.MeasuredPhase3rdHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement MeasuredPhase3rdHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase3rdHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase3rdHarmonicCurrent()
        : SubscribeAttribute("measured-phase3rd-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase3rdHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredPhase3rdHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase3rdHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase5thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase5thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase5thHarmonicCurrent()
        : ReadAttribute("measured-phase5th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase5thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasuredPhase5thHarmonicCurrentWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.MeasuredPhase5thHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement MeasuredPhase5thHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase5thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase5thHarmonicCurrent()
        : SubscribeAttribute("measured-phase5th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase5thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredPhase5thHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase5thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase7thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase7thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase7thHarmonicCurrent()
        : ReadAttribute("measured-phase7th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase7thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000310) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasuredPhase7thHarmonicCurrentWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.MeasuredPhase7thHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement MeasuredPhase7thHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase7thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase7thHarmonicCurrent()
        : SubscribeAttribute("measured-phase7th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase7thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000310) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredPhase7thHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase7thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase9thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase9thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase9thHarmonicCurrent()
        : ReadAttribute("measured-phase9th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase9thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000311) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasuredPhase9thHarmonicCurrentWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.MeasuredPhase9thHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement MeasuredPhase9thHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase9thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase9thHarmonicCurrent()
        : SubscribeAttribute("measured-phase9th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase9thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000311) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredPhase9thHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase9thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase11thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase11thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase11thHarmonicCurrent()
        : ReadAttribute("measured-phase11th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase11thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000312) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasuredPhase11thHarmonicCurrentWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.MeasuredPhase11thHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement MeasuredPhase11thHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase11thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase11thHarmonicCurrent()
        : SubscribeAttribute("measured-phase11th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase11thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000312) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeMeasuredPhase11thHarmonicCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase11thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcFrequencyMultiplier
 */
class ReadElectricalMeasurementAcFrequencyMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementAcFrequencyMultiplier()
        : ReadAttribute("ac-frequency-multiplier")
    {
    }

    ~ReadElectricalMeasurementAcFrequencyMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000400) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcFrequencyMultiplierWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcFrequencyMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcFrequencyMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcFrequencyMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcFrequencyMultiplier()
        : SubscribeAttribute("ac-frequency-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcFrequencyMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000400) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcFrequencyMultiplierWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcFrequencyMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcFrequencyDivisor
 */
class ReadElectricalMeasurementAcFrequencyDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementAcFrequencyDivisor()
        : ReadAttribute("ac-frequency-divisor")
    {
    }

    ~ReadElectricalMeasurementAcFrequencyDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000401) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcFrequencyDivisorWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcFrequencyDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcFrequencyDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcFrequencyDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcFrequencyDivisor()
        : SubscribeAttribute("ac-frequency-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcFrequencyDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000401) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcFrequencyDivisorWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcFrequencyDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PowerMultiplier
 */
class ReadElectricalMeasurementPowerMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementPowerMultiplier()
        : ReadAttribute("power-multiplier")
    {
    }

    ~ReadElectricalMeasurementPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000402) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributePowerMultiplierWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PowerMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PowerMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPowerMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPowerMultiplier()
        : SubscribeAttribute("power-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000402) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePowerMultiplierWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PowerMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PowerDivisor
 */
class ReadElectricalMeasurementPowerDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementPowerDivisor()
        : ReadAttribute("power-divisor")
    {
    }

    ~ReadElectricalMeasurementPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000403) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributePowerDivisorWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PowerDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PowerDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPowerDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPowerDivisor()
        : SubscribeAttribute("power-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000403) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePowerDivisorWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PowerDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HarmonicCurrentMultiplier
 */
class ReadElectricalMeasurementHarmonicCurrentMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementHarmonicCurrentMultiplier()
        : ReadAttribute("harmonic-current-multiplier")
    {
    }

    ~ReadElectricalMeasurementHarmonicCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000404) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeHarmonicCurrentMultiplierWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.HarmonicCurrentMultiplier response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement HarmonicCurrentMultiplier read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementHarmonicCurrentMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementHarmonicCurrentMultiplier()
        : SubscribeAttribute("harmonic-current-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementHarmonicCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000404) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeHarmonicCurrentMultiplierWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.HarmonicCurrentMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhaseHarmonicCurrentMultiplier
 */
class ReadElectricalMeasurementPhaseHarmonicCurrentMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementPhaseHarmonicCurrentMultiplier()
        : ReadAttribute("phase-harmonic-current-multiplier")
    {
    }

    ~ReadElectricalMeasurementPhaseHarmonicCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000405) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributePhaseHarmonicCurrentMultiplierWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PhaseHarmonicCurrentMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PhaseHarmonicCurrentMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPhaseHarmonicCurrentMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPhaseHarmonicCurrentMultiplier()
        : SubscribeAttribute("phase-harmonic-current-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPhaseHarmonicCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000405) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePhaseHarmonicCurrentMultiplierWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PhaseHarmonicCurrentMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstantaneousVoltage
 */
class ReadElectricalMeasurementInstantaneousVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementInstantaneousVoltage()
        : ReadAttribute("instantaneous-voltage")
    {
    }

    ~ReadElectricalMeasurementInstantaneousVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000500) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeInstantaneousVoltageWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.InstantaneousVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement InstantaneousVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementInstantaneousVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementInstantaneousVoltage()
        : SubscribeAttribute("instantaneous-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementInstantaneousVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000500) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInstantaneousVoltageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstantaneousLineCurrent
 */
class ReadElectricalMeasurementInstantaneousLineCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementInstantaneousLineCurrent()
        : ReadAttribute("instantaneous-line-current")
    {
    }

    ~ReadElectricalMeasurementInstantaneousLineCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000501) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeInstantaneousLineCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousLineCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement InstantaneousLineCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementInstantaneousLineCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementInstantaneousLineCurrent()
        : SubscribeAttribute("instantaneous-line-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementInstantaneousLineCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000501) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInstantaneousLineCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousLineCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstantaneousActiveCurrent
 */
class ReadElectricalMeasurementInstantaneousActiveCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementInstantaneousActiveCurrent()
        : ReadAttribute("instantaneous-active-current")
    {
    }

    ~ReadElectricalMeasurementInstantaneousActiveCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000502) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeInstantaneousActiveCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousActiveCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement InstantaneousActiveCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementInstantaneousActiveCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementInstantaneousActiveCurrent()
        : SubscribeAttribute("instantaneous-active-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementInstantaneousActiveCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000502) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInstantaneousActiveCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousActiveCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstantaneousReactiveCurrent
 */
class ReadElectricalMeasurementInstantaneousReactiveCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementInstantaneousReactiveCurrent()
        : ReadAttribute("instantaneous-reactive-current")
    {
    }

    ~ReadElectricalMeasurementInstantaneousReactiveCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000503) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeInstantaneousReactiveCurrentWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.InstantaneousReactiveCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement InstantaneousReactiveCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementInstantaneousReactiveCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementInstantaneousReactiveCurrent()
        : SubscribeAttribute("instantaneous-reactive-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementInstantaneousReactiveCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000503) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInstantaneousReactiveCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousReactiveCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstantaneousPower
 */
class ReadElectricalMeasurementInstantaneousPower : public ReadAttribute {
public:
    ReadElectricalMeasurementInstantaneousPower()
        : ReadAttribute("instantaneous-power")
    {
    }

    ~ReadElectricalMeasurementInstantaneousPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000504) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeInstantaneousPowerWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.InstantaneousPower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement InstantaneousPower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementInstantaneousPower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementInstantaneousPower()
        : SubscribeAttribute("instantaneous-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementInstantaneousPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000504) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInstantaneousPowerWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousPower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltage
 */
class ReadElectricalMeasurementRmsVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltage()
        : ReadAttribute("rms-voltage")
    {
    }

    ~ReadElectricalMeasurementRmsVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000505) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltage()
        : SubscribeAttribute("rms-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000505) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMin
 */
class ReadElectricalMeasurementRmsVoltageMin : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMin()
        : ReadAttribute("rms-voltage-min")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000506) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMinWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMin()
        : SubscribeAttribute("rms-voltage-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000506) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageMinWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMax
 */
class ReadElectricalMeasurementRmsVoltageMax : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMax()
        : ReadAttribute("rms-voltage-max")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000507) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMax()
        : SubscribeAttribute("rms-voltage-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000507) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrent
 */
class ReadElectricalMeasurementRmsCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrent()
        : ReadAttribute("rms-current")
    {
    }

    ~ReadElectricalMeasurementRmsCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000508) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrent()
        : SubscribeAttribute("rms-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000508) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsCurrentWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMin
 */
class ReadElectricalMeasurementRmsCurrentMin : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMin()
        : ReadAttribute("rms-current-min")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000509) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMinWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMin()
        : SubscribeAttribute("rms-current-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000509) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsCurrentMinWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMax
 */
class ReadElectricalMeasurementRmsCurrentMax : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMax()
        : ReadAttribute("rms-current-max")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMax()
        : SubscribeAttribute("rms-current-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsCurrentMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePower
 */
class ReadElectricalMeasurementActivePower : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePower()
        : ReadAttribute("active-power")
    {
    }

    ~ReadElectricalMeasurementActivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePower()
        : SubscribeAttribute("active-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActivePowerWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMin
 */
class ReadElectricalMeasurementActivePowerMin : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMin()
        : ReadAttribute("active-power-min")
    {
    }

    ~ReadElectricalMeasurementActivePowerMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMinWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMin()
        : SubscribeAttribute("active-power-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActivePowerMinWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMax
 */
class ReadElectricalMeasurementActivePowerMax : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMax()
        : ReadAttribute("active-power-max")
    {
    }

    ~ReadElectricalMeasurementActivePowerMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMaxWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMax()
        : SubscribeAttribute("active-power-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActivePowerMaxWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ReactivePower
 */
class ReadElectricalMeasurementReactivePower : public ReadAttribute {
public:
    ReadElectricalMeasurementReactivePower()
        : ReadAttribute("reactive-power")
    {
    }

    ~ReadElectricalMeasurementReactivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeReactivePowerWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ReactivePower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ReactivePower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementReactivePower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementReactivePower()
        : SubscribeAttribute("reactive-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementReactivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeReactivePowerWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ReactivePower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApparentPower
 */
class ReadElectricalMeasurementApparentPower : public ReadAttribute {
public:
    ReadElectricalMeasurementApparentPower()
        : ReadAttribute("apparent-power")
    {
    }

    ~ReadElectricalMeasurementApparentPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeApparentPowerWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ApparentPower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ApparentPower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementApparentPower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementApparentPower()
        : SubscribeAttribute("apparent-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementApparentPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeApparentPowerWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ApparentPower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PowerFactor
 */
class ReadElectricalMeasurementPowerFactor : public ReadAttribute {
public:
    ReadElectricalMeasurementPowerFactor()
        : ReadAttribute("power-factor")
    {
    }

    ~ReadElectricalMeasurementPowerFactor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000510) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributePowerFactorWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PowerFactor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PowerFactor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPowerFactor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPowerFactor()
        : SubscribeAttribute("power-factor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPowerFactor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000510) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePowerFactorWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PowerFactor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsVoltageMeasurementPeriod
 */
class ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriod : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriod()
        : ReadAttribute("average-rms-voltage-measurement-period")
    {
    }

    ~ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000511) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsVoltageMeasurementPeriodWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsVoltageMeasurementPeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementAverageRmsVoltageMeasurementPeriod : public WriteAttribute {
public:
    WriteElectricalMeasurementAverageRmsVoltageMeasurementPeriod()
        : WriteAttribute("average-rms-voltage-measurement-period")
    {
        AddArgument("attr-name", "average-rms-voltage-measurement-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementAverageRmsVoltageMeasurementPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000511) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeAverageRmsVoltageMeasurementPeriodWithValue:value
                                                                    params:params
                                                         completionHandler:^(NSError * _Nullable error) {
                                                             if (error != nil) {
                                                                 LogNSError("ElectricalMeasurement "
                                                                            "AverageRmsVoltageMeasurementPeriod write Error",
                                                                     error);
                                                             }
                                                             SetCommandExitStatus(error);
                                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriod : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriod()
        : SubscribeAttribute("average-rms-voltage-measurement-period")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000511) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAverageRmsVoltageMeasurementPeriodWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsUnderVoltageCounter
 */
class ReadElectricalMeasurementAverageRmsUnderVoltageCounter : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsUnderVoltageCounter()
        : ReadAttribute("average-rms-under-voltage-counter")
    {
    }

    ~ReadElectricalMeasurementAverageRmsUnderVoltageCounter() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000513) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsUnderVoltageCounterWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounter response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsUnderVoltageCounter read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementAverageRmsUnderVoltageCounter : public WriteAttribute {
public:
    WriteElectricalMeasurementAverageRmsUnderVoltageCounter()
        : WriteAttribute("average-rms-under-voltage-counter")
    {
        AddArgument("attr-name", "average-rms-under-voltage-counter");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementAverageRmsUnderVoltageCounter() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000513) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeAverageRmsUnderVoltageCounterWithValue:value
                                                          params:params
                                               completionHandler:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("ElectricalMeasurement AverageRmsUnderVoltageCounter write Error",
                                                           error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounter : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounter()
        : SubscribeAttribute("average-rms-under-voltage-counter")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounter() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000513) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAverageRmsUnderVoltageCounterWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounter response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeOverVoltagePeriod
 */
class ReadElectricalMeasurementRmsExtremeOverVoltagePeriod : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeOverVoltagePeriod()
        : ReadAttribute("rms-extreme-over-voltage-period")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeOverVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000514) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeRmsExtremeOverVoltagePeriodWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriod response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement RmsExtremeOverVoltagePeriod read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementRmsExtremeOverVoltagePeriod : public WriteAttribute {
public:
    WriteElectricalMeasurementRmsExtremeOverVoltagePeriod()
        : WriteAttribute("rms-extreme-over-voltage-period")
    {
        AddArgument("attr-name", "rms-extreme-over-voltage-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementRmsExtremeOverVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000514) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeRmsExtremeOverVoltagePeriodWithValue:value
                                                        params:params
                                             completionHandler:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError(
                                                         "ElectricalMeasurement RmsExtremeOverVoltagePeriod write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriod : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriod()
        : SubscribeAttribute("rms-extreme-over-voltage-period")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000514) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsExtremeOverVoltagePeriodWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeUnderVoltagePeriod
 */
class ReadElectricalMeasurementRmsExtremeUnderVoltagePeriod : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeUnderVoltagePeriod()
        : ReadAttribute("rms-extreme-under-voltage-period")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeUnderVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000515) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeUnderVoltagePeriodWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeUnderVoltagePeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementRmsExtremeUnderVoltagePeriod : public WriteAttribute {
public:
    WriteElectricalMeasurementRmsExtremeUnderVoltagePeriod()
        : WriteAttribute("rms-extreme-under-voltage-period")
    {
        AddArgument("attr-name", "rms-extreme-under-voltage-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementRmsExtremeUnderVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000515) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeRmsExtremeUnderVoltagePeriodWithValue:value
                                                         params:params
                                              completionHandler:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError(
                                                          "ElectricalMeasurement RmsExtremeUnderVoltagePeriod write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriod : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriod()
        : SubscribeAttribute("rms-extreme-under-voltage-period")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000515) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsExtremeUnderVoltagePeriodWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSagPeriod
 */
class ReadElectricalMeasurementRmsVoltageSagPeriod : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSagPeriod()
        : ReadAttribute("rms-voltage-sag-period")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSagPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000516) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSagPeriodWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSagPeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementRmsVoltageSagPeriod : public WriteAttribute {
public:
    WriteElectricalMeasurementRmsVoltageSagPeriod()
        : WriteAttribute("rms-voltage-sag-period")
    {
        AddArgument("attr-name", "rms-voltage-sag-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementRmsVoltageSagPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000516) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeRmsVoltageSagPeriodWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("ElectricalMeasurement RmsVoltageSagPeriod write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriod : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriod()
        : SubscribeAttribute("rms-voltage-sag-period")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000516) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageSagPeriodWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSwellPeriod
 */
class ReadElectricalMeasurementRmsVoltageSwellPeriod : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSwellPeriod()
        : ReadAttribute("rms-voltage-swell-period")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSwellPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000517) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSwellPeriodWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSwellPeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementRmsVoltageSwellPeriod : public WriteAttribute {
public:
    WriteElectricalMeasurementRmsVoltageSwellPeriod()
        : WriteAttribute("rms-voltage-swell-period")
    {
        AddArgument("attr-name", "rms-voltage-swell-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementRmsVoltageSwellPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000517) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeRmsVoltageSwellPeriodWithValue:value
                                                       params:params
                                            completionHandler:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("ElectricalMeasurement RmsVoltageSwellPeriod write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriod : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriod()
        : SubscribeAttribute("rms-voltage-swell-period")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000517) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageSwellPeriodWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcVoltageMultiplier
 */
class ReadElectricalMeasurementAcVoltageMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementAcVoltageMultiplier()
        : ReadAttribute("ac-voltage-multiplier")
    {
    }

    ~ReadElectricalMeasurementAcVoltageMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000600) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcVoltageMultiplierWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcVoltageMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcVoltageMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcVoltageMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcVoltageMultiplier()
        : SubscribeAttribute("ac-voltage-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcVoltageMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000600) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcVoltageMultiplierWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcVoltageMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcVoltageDivisor
 */
class ReadElectricalMeasurementAcVoltageDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementAcVoltageDivisor()
        : ReadAttribute("ac-voltage-divisor")
    {
    }

    ~ReadElectricalMeasurementAcVoltageDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000601) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcVoltageDivisorWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcVoltageDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcVoltageDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcVoltageDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcVoltageDivisor()
        : SubscribeAttribute("ac-voltage-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcVoltageDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000601) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcVoltageDivisorWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcVoltageDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcCurrentMultiplier
 */
class ReadElectricalMeasurementAcCurrentMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementAcCurrentMultiplier()
        : ReadAttribute("ac-current-multiplier")
    {
    }

    ~ReadElectricalMeasurementAcCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000602) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcCurrentMultiplierWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcCurrentMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcCurrentMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcCurrentMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcCurrentMultiplier()
        : SubscribeAttribute("ac-current-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000602) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcCurrentMultiplierWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcCurrentMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcCurrentDivisor
 */
class ReadElectricalMeasurementAcCurrentDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementAcCurrentDivisor()
        : ReadAttribute("ac-current-divisor")
    {
    }

    ~ReadElectricalMeasurementAcCurrentDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000603) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcCurrentDivisorWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcCurrentDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcCurrentDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcCurrentDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcCurrentDivisor()
        : SubscribeAttribute("ac-current-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcCurrentDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000603) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcCurrentDivisorWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcCurrentDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcPowerMultiplier
 */
class ReadElectricalMeasurementAcPowerMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementAcPowerMultiplier()
        : ReadAttribute("ac-power-multiplier")
    {
    }

    ~ReadElectricalMeasurementAcPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000604) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcPowerMultiplierWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcPowerMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcPowerMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcPowerMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcPowerMultiplier()
        : SubscribeAttribute("ac-power-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000604) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcPowerMultiplierWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcPowerMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcPowerDivisor
 */
class ReadElectricalMeasurementAcPowerDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementAcPowerDivisor()
        : ReadAttribute("ac-power-divisor")
    {
    }

    ~ReadElectricalMeasurementAcPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000605) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcPowerDivisorWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcPowerDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcPowerDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcPowerDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcPowerDivisor()
        : SubscribeAttribute("ac-power-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000605) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcPowerDivisorWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcPowerDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OverloadAlarmsMask
 */
class ReadElectricalMeasurementOverloadAlarmsMask : public ReadAttribute {
public:
    ReadElectricalMeasurementOverloadAlarmsMask()
        : ReadAttribute("overload-alarms-mask")
    {
    }

    ~ReadElectricalMeasurementOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000700) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeOverloadAlarmsMaskWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.OverloadAlarmsMask response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement OverloadAlarmsMask read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementOverloadAlarmsMask : public WriteAttribute {
public:
    WriteElectricalMeasurementOverloadAlarmsMask()
        : WriteAttribute("overload-alarms-mask")
    {
        AddArgument("attr-name", "overload-alarms-mask");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000700) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOverloadAlarmsMaskWithValue:value
                                                    params:params
                                         completionHandler:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("ElectricalMeasurement OverloadAlarmsMask write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeElectricalMeasurementOverloadAlarmsMask : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementOverloadAlarmsMask()
        : SubscribeAttribute("overload-alarms-mask")
    {
    }

    ~SubscribeAttributeElectricalMeasurementOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000700) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOverloadAlarmsMaskWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.OverloadAlarmsMask response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VoltageOverload
 */
class ReadElectricalMeasurementVoltageOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementVoltageOverload()
        : ReadAttribute("voltage-overload")
    {
    }

    ~ReadElectricalMeasurementVoltageOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000701) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeVoltageOverloadWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.VoltageOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement VoltageOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementVoltageOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementVoltageOverload()
        : SubscribeAttribute("voltage-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementVoltageOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000701) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeVoltageOverloadWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.VoltageOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentOverload
 */
class ReadElectricalMeasurementCurrentOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementCurrentOverload()
        : ReadAttribute("current-overload")
    {
    }

    ~ReadElectricalMeasurementCurrentOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000702) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeCurrentOverloadWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.CurrentOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement CurrentOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementCurrentOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementCurrentOverload()
        : SubscribeAttribute("current-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementCurrentOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000702) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCurrentOverloadWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.CurrentOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcOverloadAlarmsMask
 */
class ReadElectricalMeasurementAcOverloadAlarmsMask : public ReadAttribute {
public:
    ReadElectricalMeasurementAcOverloadAlarmsMask()
        : ReadAttribute("ac-overload-alarms-mask")
    {
    }

    ~ReadElectricalMeasurementAcOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000800) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcOverloadAlarmsMaskWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcOverloadAlarmsMask response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcOverloadAlarmsMask read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementAcOverloadAlarmsMask : public WriteAttribute {
public:
    WriteElectricalMeasurementAcOverloadAlarmsMask()
        : WriteAttribute("ac-overload-alarms-mask")
    {
        AddArgument("attr-name", "ac-overload-alarms-mask");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementAcOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000800) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeAcOverloadAlarmsMaskWithValue:value
                                                      params:params
                                           completionHandler:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("ElectricalMeasurement AcOverloadAlarmsMask write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementAcOverloadAlarmsMask : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcOverloadAlarmsMask()
        : SubscribeAttribute("ac-overload-alarms-mask")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000800) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcOverloadAlarmsMaskWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcOverloadAlarmsMask response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcVoltageOverload
 */
class ReadElectricalMeasurementAcVoltageOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementAcVoltageOverload()
        : ReadAttribute("ac-voltage-overload")
    {
    }

    ~ReadElectricalMeasurementAcVoltageOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000801) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcVoltageOverloadWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcVoltageOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcVoltageOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcVoltageOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcVoltageOverload()
        : SubscribeAttribute("ac-voltage-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcVoltageOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000801) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcVoltageOverloadWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcVoltageOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcCurrentOverload
 */
class ReadElectricalMeasurementAcCurrentOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementAcCurrentOverload()
        : ReadAttribute("ac-current-overload")
    {
    }

    ~ReadElectricalMeasurementAcCurrentOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000802) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcCurrentOverloadWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcCurrentOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcCurrentOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcCurrentOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcCurrentOverload()
        : SubscribeAttribute("ac-current-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcCurrentOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000802) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcCurrentOverloadWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcCurrentOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcActivePowerOverload
 */
class ReadElectricalMeasurementAcActivePowerOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementAcActivePowerOverload()
        : ReadAttribute("ac-active-power-overload")
    {
    }

    ~ReadElectricalMeasurementAcActivePowerOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000803) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcActivePowerOverloadWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcActivePowerOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcActivePowerOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcActivePowerOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcActivePowerOverload()
        : SubscribeAttribute("ac-active-power-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcActivePowerOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000803) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcActivePowerOverloadWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcActivePowerOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcReactivePowerOverload
 */
class ReadElectricalMeasurementAcReactivePowerOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementAcReactivePowerOverload()
        : ReadAttribute("ac-reactive-power-overload")
    {
    }

    ~ReadElectricalMeasurementAcReactivePowerOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000804) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeAcReactivePowerOverloadWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcReactivePowerOverload response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement AcReactivePowerOverload read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcReactivePowerOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcReactivePowerOverload()
        : SubscribeAttribute("ac-reactive-power-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcReactivePowerOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000804) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcReactivePowerOverloadWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcReactivePowerOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsOverVoltage
 */
class ReadElectricalMeasurementAverageRmsOverVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsOverVoltage()
        : ReadAttribute("average-rms-over-voltage")
    {
    }

    ~ReadElectricalMeasurementAverageRmsOverVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000805) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsOverVoltageWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsOverVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsOverVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsOverVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsOverVoltage()
        : SubscribeAttribute("average-rms-over-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsOverVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000805) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAverageRmsOverVoltageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsOverVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsUnderVoltage
 */
class ReadElectricalMeasurementAverageRmsUnderVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsUnderVoltage()
        : ReadAttribute("average-rms-under-voltage")
    {
    }

    ~ReadElectricalMeasurementAverageRmsUnderVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000806) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsUnderVoltageWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsUnderVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltage()
        : SubscribeAttribute("average-rms-under-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000806) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAverageRmsUnderVoltageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeOverVoltage
 */
class ReadElectricalMeasurementRmsExtremeOverVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeOverVoltage()
        : ReadAttribute("rms-extreme-over-voltage")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeOverVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000807) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeOverVoltageWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeOverVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltage()
        : SubscribeAttribute("rms-extreme-over-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000807) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsExtremeOverVoltageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeUnderVoltage
 */
class ReadElectricalMeasurementRmsExtremeUnderVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeUnderVoltage()
        : ReadAttribute("rms-extreme-under-voltage")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeUnderVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000808) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeUnderVoltageWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeUnderVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltage()
        : SubscribeAttribute("rms-extreme-under-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000808) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsExtremeUnderVoltageWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSag
 */
class ReadElectricalMeasurementRmsVoltageSag : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSag()
        : ReadAttribute("rms-voltage-sag")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSag() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000809) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSagWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSag response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSag read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSag : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSag()
        : SubscribeAttribute("rms-voltage-sag")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSag() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000809) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageSagWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSag response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSwell
 */
class ReadElectricalMeasurementRmsVoltageSwell : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSwell()
        : ReadAttribute("rms-voltage-swell")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSwell() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000080A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSwellWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSwell response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSwell read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSwell : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSwell()
        : SubscribeAttribute("rms-voltage-swell")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSwell() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000080A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageSwellWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSwell response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LineCurrentPhaseB
 */
class ReadElectricalMeasurementLineCurrentPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementLineCurrentPhaseB()
        : ReadAttribute("line-current-phase-b")
    {
    }

    ~ReadElectricalMeasurementLineCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000901) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeLineCurrentPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.LineCurrentPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement LineCurrentPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementLineCurrentPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementLineCurrentPhaseB()
        : SubscribeAttribute("line-current-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementLineCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000901) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLineCurrentPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.LineCurrentPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveCurrentPhaseB
 */
class ReadElectricalMeasurementActiveCurrentPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementActiveCurrentPhaseB()
        : ReadAttribute("active-current-phase-b")
    {
    }

    ~ReadElectricalMeasurementActiveCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000902) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActiveCurrentPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActiveCurrentPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActiveCurrentPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActiveCurrentPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActiveCurrentPhaseB()
        : SubscribeAttribute("active-current-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActiveCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000902) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveCurrentPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActiveCurrentPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ReactiveCurrentPhaseB
 */
class ReadElectricalMeasurementReactiveCurrentPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementReactiveCurrentPhaseB()
        : ReadAttribute("reactive-current-phase-b")
    {
    }

    ~ReadElectricalMeasurementReactiveCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000903) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeReactiveCurrentPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ReactiveCurrentPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ReactiveCurrentPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseB()
        : SubscribeAttribute("reactive-current-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000903) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeReactiveCurrentPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ReactiveCurrentPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltagePhaseB
 */
class ReadElectricalMeasurementRmsVoltagePhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltagePhaseB()
        : ReadAttribute("rms-voltage-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsVoltagePhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000905) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltagePhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltagePhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltagePhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltagePhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltagePhaseB()
        : SubscribeAttribute("rms-voltage-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltagePhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000905) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltagePhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltagePhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMinPhaseB
 */
class ReadElectricalMeasurementRmsVoltageMinPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMinPhaseB()
        : ReadAttribute("rms-voltage-min-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000906) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMinPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMinPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMinPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseB()
        : SubscribeAttribute("rms-voltage-min-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000906) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageMinPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMinPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMaxPhaseB
 */
class ReadElectricalMeasurementRmsVoltageMaxPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMaxPhaseB()
        : ReadAttribute("rms-voltage-max-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000907) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMaxPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMaxPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMaxPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseB()
        : SubscribeAttribute("rms-voltage-max-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000907) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageMaxPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMaxPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentPhaseB
 */
class ReadElectricalMeasurementRmsCurrentPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentPhaseB()
        : ReadAttribute("rms-current-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000908) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentPhaseB()
        : SubscribeAttribute("rms-current-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000908) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsCurrentPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMinPhaseB
 */
class ReadElectricalMeasurementRmsCurrentMinPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMinPhaseB()
        : ReadAttribute("rms-current-min-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000909) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMinPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMinPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMinPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseB()
        : SubscribeAttribute("rms-current-min-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000909) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsCurrentMinPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMinPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMaxPhaseB
 */
class ReadElectricalMeasurementRmsCurrentMaxPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMaxPhaseB()
        : ReadAttribute("rms-current-max-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMaxPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMaxPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMaxPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseB()
        : SubscribeAttribute("rms-current-max-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsCurrentMaxPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMaxPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerPhaseB
 */
class ReadElectricalMeasurementActivePowerPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerPhaseB()
        : ReadAttribute("active-power-phase-b")
    {
    }

    ~ReadElectricalMeasurementActivePowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerPhaseB()
        : SubscribeAttribute("active-power-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActivePowerPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMinPhaseB
 */
class ReadElectricalMeasurementActivePowerMinPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMinPhaseB()
        : ReadAttribute("active-power-min-phase-b")
    {
    }

    ~ReadElectricalMeasurementActivePowerMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMinPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMinPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMinPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMinPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMinPhaseB()
        : SubscribeAttribute("active-power-min-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActivePowerMinPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMinPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMaxPhaseB
 */
class ReadElectricalMeasurementActivePowerMaxPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMaxPhaseB()
        : ReadAttribute("active-power-max-phase-b")
    {
    }

    ~ReadElectricalMeasurementActivePowerMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMaxPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMaxPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMaxPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseB()
        : SubscribeAttribute("active-power-max-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActivePowerMaxPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMaxPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ReactivePowerPhaseB
 */
class ReadElectricalMeasurementReactivePowerPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementReactivePowerPhaseB()
        : ReadAttribute("reactive-power-phase-b")
    {
    }

    ~ReadElectricalMeasurementReactivePowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeReactivePowerPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ReactivePowerPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ReactivePowerPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementReactivePowerPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementReactivePowerPhaseB()
        : SubscribeAttribute("reactive-power-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementReactivePowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeReactivePowerPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ReactivePowerPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApparentPowerPhaseB
 */
class ReadElectricalMeasurementApparentPowerPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementApparentPowerPhaseB()
        : ReadAttribute("apparent-power-phase-b")
    {
    }

    ~ReadElectricalMeasurementApparentPowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeApparentPowerPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ApparentPowerPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ApparentPowerPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementApparentPowerPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementApparentPowerPhaseB()
        : SubscribeAttribute("apparent-power-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementApparentPowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeApparentPowerPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ApparentPowerPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PowerFactorPhaseB
 */
class ReadElectricalMeasurementPowerFactorPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementPowerFactorPhaseB()
        : ReadAttribute("power-factor-phase-b")
    {
    }

    ~ReadElectricalMeasurementPowerFactorPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000910) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributePowerFactorPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PowerFactorPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PowerFactorPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPowerFactorPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPowerFactorPhaseB()
        : SubscribeAttribute("power-factor-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPowerFactorPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000910) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePowerFactorPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PowerFactorPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsVoltageMeasurementPeriodPhaseB
 */
class ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB()
        : ReadAttribute("average-rms-voltage-measurement-period-phase-b")
    {
    }

    ~ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000911) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsVoltageMeasurementPeriodPhaseBWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriodPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsVoltageMeasurementPeriodPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB()
        : SubscribeAttribute("average-rms-voltage-measurement-period-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000911) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster
            subscribeAttributeAverageRmsVoltageMeasurementPeriodPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriodPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsOverVoltageCounterPhaseB
 */
class ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseB()
        : ReadAttribute("average-rms-over-voltage-counter-phase-b")
    {
    }

    ~ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000912) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsOverVoltageCounterPhaseBWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsOverVoltageCounterPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsOverVoltageCounterPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseB()
        : SubscribeAttribute("average-rms-over-voltage-counter-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000912) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAverageRmsOverVoltageCounterPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsOverVoltageCounterPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsUnderVoltageCounterPhaseB
 */
class ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB()
        : ReadAttribute("average-rms-under-voltage-counter-phase-b")
    {
    }

    ~ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000913) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsUnderVoltageCounterPhaseBWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounterPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsUnderVoltageCounterPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB()
        : SubscribeAttribute("average-rms-under-voltage-counter-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000913) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAverageRmsUnderVoltageCounterPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounterPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeOverVoltagePeriodPhaseB
 */
class ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB()
        : ReadAttribute("rms-extreme-over-voltage-period-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000914) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeOverVoltagePeriodPhaseBWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriodPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeOverVoltagePeriodPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB()
        : SubscribeAttribute("rms-extreme-over-voltage-period-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000914) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsExtremeOverVoltagePeriodPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriodPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeUnderVoltagePeriodPhaseB
 */
class ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB()
        : ReadAttribute("rms-extreme-under-voltage-period-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000915) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeUnderVoltagePeriodPhaseBWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriodPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeUnderVoltagePeriodPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB()
        : SubscribeAttribute("rms-extreme-under-voltage-period-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000915) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsExtremeUnderVoltagePeriodPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriodPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSagPeriodPhaseB
 */
class ReadElectricalMeasurementRmsVoltageSagPeriodPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSagPeriodPhaseB()
        : ReadAttribute("rms-voltage-sag-period-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSagPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000916) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeRmsVoltageSagPeriodPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriodPhaseB response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement RmsVoltageSagPeriodPhaseB read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseB()
        : SubscribeAttribute("rms-voltage-sag-period-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000916) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageSagPeriodPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriodPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSwellPeriodPhaseB
 */
class ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseB()
        : ReadAttribute("rms-voltage-swell-period-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000917) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeRmsVoltageSwellPeriodPhaseBWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriodPhaseB response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement RmsVoltageSwellPeriodPhaseB read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseB()
        : SubscribeAttribute("rms-voltage-swell-period-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000917) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageSwellPeriodPhaseBWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriodPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LineCurrentPhaseC
 */
class ReadElectricalMeasurementLineCurrentPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementLineCurrentPhaseC()
        : ReadAttribute("line-current-phase-c")
    {
    }

    ~ReadElectricalMeasurementLineCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A01) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeLineCurrentPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.LineCurrentPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement LineCurrentPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementLineCurrentPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementLineCurrentPhaseC()
        : SubscribeAttribute("line-current-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementLineCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A01) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLineCurrentPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.LineCurrentPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveCurrentPhaseC
 */
class ReadElectricalMeasurementActiveCurrentPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementActiveCurrentPhaseC()
        : ReadAttribute("active-current-phase-c")
    {
    }

    ~ReadElectricalMeasurementActiveCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A02) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActiveCurrentPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActiveCurrentPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActiveCurrentPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActiveCurrentPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActiveCurrentPhaseC()
        : SubscribeAttribute("active-current-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActiveCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A02) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActiveCurrentPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActiveCurrentPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ReactiveCurrentPhaseC
 */
class ReadElectricalMeasurementReactiveCurrentPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementReactiveCurrentPhaseC()
        : ReadAttribute("reactive-current-phase-c")
    {
    }

    ~ReadElectricalMeasurementReactiveCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A03) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeReactiveCurrentPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ReactiveCurrentPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ReactiveCurrentPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseC()
        : SubscribeAttribute("reactive-current-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A03) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeReactiveCurrentPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ReactiveCurrentPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltagePhaseC
 */
class ReadElectricalMeasurementRmsVoltagePhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltagePhaseC()
        : ReadAttribute("rms-voltage-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsVoltagePhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A05) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltagePhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltagePhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltagePhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltagePhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltagePhaseC()
        : SubscribeAttribute("rms-voltage-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltagePhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A05) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltagePhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltagePhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMinPhaseC
 */
class ReadElectricalMeasurementRmsVoltageMinPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMinPhaseC()
        : ReadAttribute("rms-voltage-min-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A06) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMinPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMinPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMinPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseC()
        : SubscribeAttribute("rms-voltage-min-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A06) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageMinPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMinPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMaxPhaseC
 */
class ReadElectricalMeasurementRmsVoltageMaxPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMaxPhaseC()
        : ReadAttribute("rms-voltage-max-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A07) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMaxPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMaxPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMaxPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseC()
        : SubscribeAttribute("rms-voltage-max-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A07) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageMaxPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMaxPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentPhaseC
 */
class ReadElectricalMeasurementRmsCurrentPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentPhaseC()
        : ReadAttribute("rms-current-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A08) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentPhaseC()
        : SubscribeAttribute("rms-current-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A08) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsCurrentPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMinPhaseC
 */
class ReadElectricalMeasurementRmsCurrentMinPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMinPhaseC()
        : ReadAttribute("rms-current-min-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A09) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMinPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMinPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMinPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseC()
        : SubscribeAttribute("rms-current-min-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A09) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsCurrentMinPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMinPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMaxPhaseC
 */
class ReadElectricalMeasurementRmsCurrentMaxPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMaxPhaseC()
        : ReadAttribute("rms-current-max-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMaxPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMaxPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMaxPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseC()
        : SubscribeAttribute("rms-current-max-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsCurrentMaxPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMaxPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerPhaseC
 */
class ReadElectricalMeasurementActivePowerPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerPhaseC()
        : ReadAttribute("active-power-phase-c")
    {
    }

    ~ReadElectricalMeasurementActivePowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerPhaseC()
        : SubscribeAttribute("active-power-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActivePowerPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMinPhaseC
 */
class ReadElectricalMeasurementActivePowerMinPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMinPhaseC()
        : ReadAttribute("active-power-min-phase-c")
    {
    }

    ~ReadElectricalMeasurementActivePowerMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMinPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMinPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMinPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMinPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMinPhaseC()
        : SubscribeAttribute("active-power-min-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActivePowerMinPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMinPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMaxPhaseC
 */
class ReadElectricalMeasurementActivePowerMaxPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMaxPhaseC()
        : ReadAttribute("active-power-max-phase-c")
    {
    }

    ~ReadElectricalMeasurementActivePowerMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMaxPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMaxPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMaxPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseC()
        : SubscribeAttribute("active-power-max-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeActivePowerMaxPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMaxPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ReactivePowerPhaseC
 */
class ReadElectricalMeasurementReactivePowerPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementReactivePowerPhaseC()
        : ReadAttribute("reactive-power-phase-c")
    {
    }

    ~ReadElectricalMeasurementReactivePowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeReactivePowerPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ReactivePowerPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ReactivePowerPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementReactivePowerPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementReactivePowerPhaseC()
        : SubscribeAttribute("reactive-power-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementReactivePowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeReactivePowerPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ReactivePowerPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApparentPowerPhaseC
 */
class ReadElectricalMeasurementApparentPowerPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementApparentPowerPhaseC()
        : ReadAttribute("apparent-power-phase-c")
    {
    }

    ~ReadElectricalMeasurementApparentPowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeApparentPowerPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ApparentPowerPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ApparentPowerPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementApparentPowerPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementApparentPowerPhaseC()
        : SubscribeAttribute("apparent-power-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementApparentPowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeApparentPowerPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ApparentPowerPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PowerFactorPhaseC
 */
class ReadElectricalMeasurementPowerFactorPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementPowerFactorPhaseC()
        : ReadAttribute("power-factor-phase-c")
    {
    }

    ~ReadElectricalMeasurementPowerFactorPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A10) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributePowerFactorPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PowerFactorPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PowerFactorPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPowerFactorPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPowerFactorPhaseC()
        : SubscribeAttribute("power-factor-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPowerFactorPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A10) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributePowerFactorPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PowerFactorPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsVoltageMeasurementPeriodPhaseC
 */
class ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC()
        : ReadAttribute("average-rms-voltage-measurement-period-phase-c")
    {
    }

    ~ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A11) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsVoltageMeasurementPeriodPhaseCWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriodPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsVoltageMeasurementPeriodPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC()
        : SubscribeAttribute("average-rms-voltage-measurement-period-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A11) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster
            subscribeAttributeAverageRmsVoltageMeasurementPeriodPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriodPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsOverVoltageCounterPhaseC
 */
class ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseC()
        : ReadAttribute("average-rms-over-voltage-counter-phase-c")
    {
    }

    ~ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A12) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsOverVoltageCounterPhaseCWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsOverVoltageCounterPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsOverVoltageCounterPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseC()
        : SubscribeAttribute("average-rms-over-voltage-counter-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A12) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAverageRmsOverVoltageCounterPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsOverVoltageCounterPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsUnderVoltageCounterPhaseC
 */
class ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC()
        : ReadAttribute("average-rms-under-voltage-counter-phase-c")
    {
    }

    ~ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A13) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsUnderVoltageCounterPhaseCWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounterPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsUnderVoltageCounterPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC()
        : SubscribeAttribute("average-rms-under-voltage-counter-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A13) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAverageRmsUnderVoltageCounterPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounterPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeOverVoltagePeriodPhaseC
 */
class ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC()
        : ReadAttribute("rms-extreme-over-voltage-period-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A14) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeOverVoltagePeriodPhaseCWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriodPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeOverVoltagePeriodPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC()
        : SubscribeAttribute("rms-extreme-over-voltage-period-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A14) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsExtremeOverVoltagePeriodPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriodPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeUnderVoltagePeriodPhaseC
 */
class ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC()
        : ReadAttribute("rms-extreme-under-voltage-period-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A15) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeUnderVoltagePeriodPhaseCWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriodPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeUnderVoltagePeriodPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC()
        : SubscribeAttribute("rms-extreme-under-voltage-period-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A15) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsExtremeUnderVoltagePeriodPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriodPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSagPeriodPhaseC
 */
class ReadElectricalMeasurementRmsVoltageSagPeriodPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSagPeriodPhaseC()
        : ReadAttribute("rms-voltage-sag-period-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSagPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A16) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeRmsVoltageSagPeriodPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriodPhaseC response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement RmsVoltageSagPeriodPhaseC read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseC()
        : SubscribeAttribute("rms-voltage-sag-period-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A16) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageSagPeriodPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriodPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSwellPeriodPhaseC
 */
class ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseC()
        : ReadAttribute("rms-voltage-swell-period-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A17) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeRmsVoltageSwellPeriodPhaseCWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriodPhaseC response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement RmsVoltageSwellPeriodPhaseC read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseC()
        : SubscribeAttribute("rms-voltage-swell-period-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A17) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRmsVoltageSwellPeriodPhaseCWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriodPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadElectricalMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadElectricalMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadElectricalMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeElectricalMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadElectricalMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadElectricalMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadElectricalMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadElectricalMeasurementAttributeList : public ReadAttribute {
public:
    ReadElectricalMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadElectricalMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadElectricalMeasurementFeatureMap : public ReadAttribute {
public:
    ReadElectricalMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadElectricalMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeElectricalMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadElectricalMeasurementClusterRevision : public ReadAttribute {
public:
    ReadElectricalMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadElectricalMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeElectricalMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                           endpoint:endpointId
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster TestCluster                                                 | 0xFFF1FC05|
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * Test                                                              |   0x00 |
| * TestNotHandled                                                    |   0x01 |
| * TestSpecific                                                      |   0x02 |
| * TestUnknownCommand                                                |   0x03 |
| * TestAddArguments                                                  |   0x04 |
| * TestSimpleArgumentRequest                                         |   0x05 |
| * TestStructArrayArgumentRequest                                    |   0x06 |
| * TestStructArgumentRequest                                         |   0x07 |
| * TestNestedStructArgumentRequest                                   |   0x08 |
| * TestListStructArgumentRequest                                     |   0x09 |
| * TestListInt8UArgumentRequest                                      |   0x0A |
| * TestNestedStructListArgumentRequest                               |   0x0B |
| * TestListNestedStructListArgumentRequest                           |   0x0C |
| * TestListInt8UReverseRequest                                       |   0x0D |
| * TestEnumsRequest                                                  |   0x0E |
| * TestNullableOptionalRequest                                       |   0x0F |
| * TestComplexNullableOptionalRequest                                |   0x10 |
| * SimpleStructEchoRequest                                           |   0x11 |
| * TimedInvokeRequest                                                |   0x12 |
| * TestSimpleOptionalArgumentRequest                                 |   0x13 |
| * TestEmitTestEventRequest                                          |   0x14 |
| * TestEmitTestFabricScopedEventRequest                              |   0x15 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Boolean                                                           | 0x0000 |
| * Bitmap8                                                           | 0x0001 |
| * Bitmap16                                                          | 0x0002 |
| * Bitmap32                                                          | 0x0003 |
| * Bitmap64                                                          | 0x0004 |
| * Int8u                                                             | 0x0005 |
| * Int16u                                                            | 0x0006 |
| * Int24u                                                            | 0x0007 |
| * Int32u                                                            | 0x0008 |
| * Int40u                                                            | 0x0009 |
| * Int48u                                                            | 0x000A |
| * Int56u                                                            | 0x000B |
| * Int64u                                                            | 0x000C |
| * Int8s                                                             | 0x000D |
| * Int16s                                                            | 0x000E |
| * Int24s                                                            | 0x000F |
| * Int32s                                                            | 0x0010 |
| * Int40s                                                            | 0x0011 |
| * Int48s                                                            | 0x0012 |
| * Int56s                                                            | 0x0013 |
| * Int64s                                                            | 0x0014 |
| * Enum8                                                             | 0x0015 |
| * Enum16                                                            | 0x0016 |
| * FloatSingle                                                       | 0x0017 |
| * FloatDouble                                                       | 0x0018 |
| * OctetString                                                       | 0x0019 |
| * ListInt8u                                                         | 0x001A |
| * ListOctetString                                                   | 0x001B |
| * ListStructOctetString                                             | 0x001C |
| * LongOctetString                                                   | 0x001D |
| * CharString                                                        | 0x001E |
| * LongCharString                                                    | 0x001F |
| * EpochUs                                                           | 0x0020 |
| * EpochS                                                            | 0x0021 |
| * VendorId                                                          | 0x0022 |
| * ListNullablesAndOptionalsStruct                                   | 0x0023 |
| * EnumAttr                                                          | 0x0024 |
| * StructAttr                                                        | 0x0025 |
| * RangeRestrictedInt8u                                              | 0x0026 |
| * RangeRestrictedInt8s                                              | 0x0027 |
| * RangeRestrictedInt16u                                             | 0x0028 |
| * RangeRestrictedInt16s                                             | 0x0029 |
| * ListLongOctetString                                               | 0x002A |
| * ListFabricScoped                                                  | 0x002B |
| * TimedWriteBoolean                                                 | 0x0030 |
| * GeneralErrorBoolean                                               | 0x0031 |
| * ClusterErrorBoolean                                               | 0x0032 |
| * Unsupported                                                       | 0x00FF |
| * NullableBoolean                                                   | 0x4000 |
| * NullableBitmap8                                                   | 0x4001 |
| * NullableBitmap16                                                  | 0x4002 |
| * NullableBitmap32                                                  | 0x4003 |
| * NullableBitmap64                                                  | 0x4004 |
| * NullableInt8u                                                     | 0x4005 |
| * NullableInt16u                                                    | 0x4006 |
| * NullableInt24u                                                    | 0x4007 |
| * NullableInt32u                                                    | 0x4008 |
| * NullableInt40u                                                    | 0x4009 |
| * NullableInt48u                                                    | 0x400A |
| * NullableInt56u                                                    | 0x400B |
| * NullableInt64u                                                    | 0x400C |
| * NullableInt8s                                                     | 0x400D |
| * NullableInt16s                                                    | 0x400E |
| * NullableInt24s                                                    | 0x400F |
| * NullableInt32s                                                    | 0x4010 |
| * NullableInt40s                                                    | 0x4011 |
| * NullableInt48s                                                    | 0x4012 |
| * NullableInt56s                                                    | 0x4013 |
| * NullableInt64s                                                    | 0x4014 |
| * NullableEnum8                                                     | 0x4015 |
| * NullableEnum16                                                    | 0x4016 |
| * NullableFloatSingle                                               | 0x4017 |
| * NullableFloatDouble                                               | 0x4018 |
| * NullableOctetString                                               | 0x4019 |
| * NullableCharString                                                | 0x401E |
| * NullableEnumAttr                                                  | 0x4024 |
| * NullableStruct                                                    | 0x4025 |
| * NullableRangeRestrictedInt8u                                      | 0x4026 |
| * NullableRangeRestrictedInt8s                                      | 0x4027 |
| * NullableRangeRestrictedInt16u                                     | 0x4028 |
| * NullableRangeRestrictedInt16s                                     | 0x4029 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * TestEvent                                                         | 0x0001 |
| * TestFabricScopedEvent                                             | 0x0002 |
\*----------------------------------------------------------------------------*/

/*
 * Command Test
 */
class TestClusterTest : public ClusterCommand {
public:
    TestClusterTest()
        : ClusterCommand("test")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testWithParams:params
                  completionHandler:^(NSError * _Nullable error) {
                      responsesNeeded--;
                      if (error != nil) {
                          mError = error;
                          LogNSError("Error", error);
                      }
                      if (responsesNeeded == 0) {
                          SetCommandExitStatus(mError);
                      }
                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command TestNotHandled
 */
class TestClusterTestNotHandled : public ClusterCommand {
public:
    TestClusterTestNotHandled()
        : ClusterCommand("test-not-handled")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestNotHandledParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testNotHandledWithParams:params
                            completionHandler:^(NSError * _Nullable error) {
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command TestSpecific
 */
class TestClusterTestSpecific : public ClusterCommand {
public:
    TestClusterTestSpecific()
        : ClusterCommand("test-specific")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestSpecificParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testSpecificWithParams:params
                          completionHandler:^(
                              MTRTestClusterClusterTestSpecificResponseParams * _Nullable values, NSError * _Nullable error) {
                              NSLog(@"Values: %@", values);
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command TestUnknownCommand
 */
class TestClusterTestUnknownCommand : public ClusterCommand {
public:
    TestClusterTestUnknownCommand()
        : ClusterCommand("test-unknown-command")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestUnknownCommandParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testUnknownCommandWithParams:params
                                completionHandler:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command TestAddArguments
 */
class TestClusterTestAddArguments : public ClusterCommand {
public:
    TestClusterTestAddArguments()
        : ClusterCommand("test-add-arguments")
    {
        AddArgument("Arg1", 0, UINT8_MAX, &mRequest.arg1);
        AddArgument("Arg2", 0, UINT8_MAX, &mRequest.arg2);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestAddArgumentsParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [NSNumber numberWithUnsignedChar:mRequest.arg1];
        params.arg2 = [NSNumber numberWithUnsignedChar:mRequest.arg2];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testAddArgumentsWithParams:params
                              completionHandler:^(MTRTestClusterClusterTestAddArgumentsResponseParams * _Nullable values,
                                  NSError * _Nullable error) {
                                  NSLog(@"Values: %@", values);
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestAddArguments::Type mRequest;
};

/*
 * Command TestSimpleArgumentRequest
 */
class TestClusterTestSimpleArgumentRequest : public ClusterCommand {
public:
    TestClusterTestSimpleArgumentRequest()
        : ClusterCommand("test-simple-argument-request")
    {
        AddArgument("Arg1", 0, 1, &mRequest.arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestSimpleArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [NSNumber numberWithBool:mRequest.arg1];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testSimpleArgumentRequestWithParams:params
                                       completionHandler:^(MTRTestClusterClusterTestSimpleArgumentResponseParams * _Nullable values,
                                           NSError * _Nullable error) {
                                           NSLog(@"Values: %@", values);
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestSimpleArgumentRequest::Type mRequest;
};

/*
 * Command TestStructArrayArgumentRequest
 */
class TestClusterTestStructArrayArgumentRequest : public ClusterCommand {
public:
    TestClusterTestStructArrayArgumentRequest()
        : ClusterCommand("test-struct-array-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
        , mComplex_Arg2(&mRequest.arg2)
        , mComplex_Arg3(&mRequest.arg3)
        , mComplex_Arg4(&mRequest.arg4)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        AddArgument("Arg2", &mComplex_Arg2);
        AddArgument("Arg3", &mComplex_Arg3);
        AddArgument("Arg4", &mComplex_Arg4);
        AddArgument("Arg5", 0, UINT8_MAX, &mRequest.arg5);
        AddArgument("Arg6", 0, 1, &mRequest.arg6);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestStructArrayArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg1) {
                MTRTestClusterClusterNestedStructList * newElement_0;
                newElement_0 = [MTRTestClusterClusterNestedStructList new];
                newElement_0.a = [NSNumber numberWithUnsignedChar:entry_0.a];
                newElement_0.b = [NSNumber numberWithBool:entry_0.b];
                newElement_0.c = [MTRTestClusterClusterSimpleStruct new];
                newElement_0.c.a = [NSNumber numberWithUnsignedChar:entry_0.c.a];
                newElement_0.c.b = [NSNumber numberWithBool:entry_0.c.b];
                newElement_0.c.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.c.c)];
                newElement_0.c.d = [NSData dataWithBytes:entry_0.c.d.data() length:entry_0.c.d.size()];
                newElement_0.c.e = [[NSString alloc] initWithBytes:entry_0.c.e.data()
                                                            length:entry_0.c.e.size()
                                                          encoding:NSUTF8StringEncoding];
                newElement_0.c.f = [NSNumber numberWithUnsignedChar:entry_0.c.f.Raw()];
                newElement_0.c.g = [NSNumber numberWithFloat:entry_0.c.g];
                newElement_0.c.h = [NSNumber numberWithDouble:entry_0.c.h];
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.d) {
                        MTRTestClusterClusterSimpleStruct * newElement_2;
                        newElement_2 = [MTRTestClusterClusterSimpleStruct new];
                        newElement_2.a = [NSNumber numberWithUnsignedChar:entry_2.a];
                        newElement_2.b = [NSNumber numberWithBool:entry_2.b];
                        newElement_2.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_2.c)];
                        newElement_2.d = [NSData dataWithBytes:entry_2.d.data() length:entry_2.d.size()];
                        newElement_2.e = [[NSString alloc] initWithBytes:entry_2.e.data()
                                                                  length:entry_2.e.size()
                                                                encoding:NSUTF8StringEncoding];
                        newElement_2.f = [NSNumber numberWithUnsignedChar:entry_2.f.Raw()];
                        newElement_2.g = [NSNumber numberWithFloat:entry_2.g];
                        newElement_2.h = [NSNumber numberWithDouble:entry_2.h];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.d = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.e) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedInt:entry_2];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.e = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.f) {
                        NSData * newElement_2;
                        newElement_2 = [NSData dataWithBytes:entry_2.data() length:entry_2.size()];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.f = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.g) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedChar:entry_2];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.g = array_2;
                }
                [array_0 addObject:newElement_0];
            }
            params.arg1 = array_0;
        }
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg2) {
                MTRTestClusterClusterSimpleStruct * newElement_0;
                newElement_0 = [MTRTestClusterClusterSimpleStruct new];
                newElement_0.a = [NSNumber numberWithUnsignedChar:entry_0.a];
                newElement_0.b = [NSNumber numberWithBool:entry_0.b];
                newElement_0.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.c)];
                newElement_0.d = [NSData dataWithBytes:entry_0.d.data() length:entry_0.d.size()];
                newElement_0.e = [[NSString alloc] initWithBytes:entry_0.e.data()
                                                          length:entry_0.e.size()
                                                        encoding:NSUTF8StringEncoding];
                newElement_0.f = [NSNumber numberWithUnsignedChar:entry_0.f.Raw()];
                newElement_0.g = [NSNumber numberWithFloat:entry_0.g];
                newElement_0.h = [NSNumber numberWithDouble:entry_0.h];
                [array_0 addObject:newElement_0];
            }
            params.arg2 = array_0;
        }
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg3) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0)];
                [array_0 addObject:newElement_0];
            }
            params.arg3 = array_0;
        }
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg4) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithBool:entry_0];
                [array_0 addObject:newElement_0];
            }
            params.arg4 = array_0;
        }
        params.arg5 = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg5)];
        params.arg6 = [NSNumber numberWithBool:mRequest.arg6];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testStructArrayArgumentRequestWithParams:params
                                            completionHandler:^(
                                                MTRTestClusterClusterTestStructArrayArgumentResponseParams * _Nullable values,
                                                NSError * _Nullable error) {
                                                NSLog(@"Values: %@", values);
                                                responsesNeeded--;
                                                if (error != nil) {
                                                    mError = error;
                                                    LogNSError("Error", error);
                                                }
                                                if (responsesNeeded == 0) {
                                                    SetCommandExitStatus(mError);
                                                }
                                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestStructArrayArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::NestedStructList::Type>>
        mComplex_Arg1;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>>
        mComplex_Arg2;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::SimpleEnum>> mComplex_Arg3;
    TypedComplexArgument<chip::app::DataModel::List<const bool>> mComplex_Arg4;
};

/*
 * Command TestStructArgumentRequest
 */
class TestClusterTestStructArgumentRequest : public ClusterCommand {
public:
    TestClusterTestStructArgumentRequest()
        : ClusterCommand("test-struct-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestStructArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRTestClusterClusterSimpleStruct new];
        params.arg1.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.a];
        params.arg1.b = [NSNumber numberWithBool:mRequest.arg1.b];
        params.arg1.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg1.c)];
        params.arg1.d = [NSData dataWithBytes:mRequest.arg1.d.data() length:mRequest.arg1.d.size()];
        params.arg1.e = [[NSString alloc] initWithBytes:mRequest.arg1.e.data()
                                                 length:mRequest.arg1.e.size()
                                               encoding:NSUTF8StringEncoding];
        params.arg1.f = [NSNumber numberWithUnsignedChar:mRequest.arg1.f.Raw()];
        params.arg1.g = [NSNumber numberWithFloat:mRequest.arg1.g];
        params.arg1.h = [NSNumber numberWithDouble:mRequest.arg1.h];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testStructArgumentRequestWithParams:params
                                       completionHandler:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                           NSError * _Nullable error) {
                                           NSLog(@"Values: %@", values);
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestStructArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type> mComplex_Arg1;
};

/*
 * Command TestNestedStructArgumentRequest
 */
class TestClusterTestNestedStructArgumentRequest : public ClusterCommand {
public:
    TestClusterTestNestedStructArgumentRequest()
        : ClusterCommand("test-nested-struct-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestNestedStructArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRTestClusterClusterNestedStruct new];
        params.arg1.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.a];
        params.arg1.b = [NSNumber numberWithBool:mRequest.arg1.b];
        params.arg1.c = [MTRTestClusterClusterSimpleStruct new];
        params.arg1.c.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.c.a];
        params.arg1.c.b = [NSNumber numberWithBool:mRequest.arg1.c.b];
        params.arg1.c.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg1.c.c)];
        params.arg1.c.d = [NSData dataWithBytes:mRequest.arg1.c.d.data() length:mRequest.arg1.c.d.size()];
        params.arg1.c.e = [[NSString alloc] initWithBytes:mRequest.arg1.c.e.data()
                                                   length:mRequest.arg1.c.e.size()
                                                 encoding:NSUTF8StringEncoding];
        params.arg1.c.f = [NSNumber numberWithUnsignedChar:mRequest.arg1.c.f.Raw()];
        params.arg1.c.g = [NSNumber numberWithFloat:mRequest.arg1.c.g];
        params.arg1.c.h = [NSNumber numberWithDouble:mRequest.arg1.c.h];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testNestedStructArgumentRequestWithParams:params
                                             completionHandler:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                                 NSError * _Nullable error) {
                                                 NSLog(@"Values: %@", values);
                                                 responsesNeeded--;
                                                 if (error != nil) {
                                                     mError = error;
                                                     LogNSError("Error", error);
                                                 }
                                                 if (responsesNeeded == 0) {
                                                     SetCommandExitStatus(mError);
                                                 }
                                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestNestedStructArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::TestCluster::Structs::NestedStruct::Type> mComplex_Arg1;
};

/*
 * Command TestListStructArgumentRequest
 */
class TestClusterTestListStructArgumentRequest : public ClusterCommand {
public:
    TestClusterTestListStructArgumentRequest()
        : ClusterCommand("test-list-struct-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestListStructArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg1) {
                MTRTestClusterClusterSimpleStruct * newElement_0;
                newElement_0 = [MTRTestClusterClusterSimpleStruct new];
                newElement_0.a = [NSNumber numberWithUnsignedChar:entry_0.a];
                newElement_0.b = [NSNumber numberWithBool:entry_0.b];
                newElement_0.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.c)];
                newElement_0.d = [NSData dataWithBytes:entry_0.d.data() length:entry_0.d.size()];
                newElement_0.e = [[NSString alloc] initWithBytes:entry_0.e.data()
                                                          length:entry_0.e.size()
                                                        encoding:NSUTF8StringEncoding];
                newElement_0.f = [NSNumber numberWithUnsignedChar:entry_0.f.Raw()];
                newElement_0.g = [NSNumber numberWithFloat:entry_0.g];
                newElement_0.h = [NSNumber numberWithDouble:entry_0.h];
                [array_0 addObject:newElement_0];
            }
            params.arg1 = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testListStructArgumentRequestWithParams:params
                                           completionHandler:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                               NSError * _Nullable error) {
                                               NSLog(@"Values: %@", values);
                                               responsesNeeded--;
                                               if (error != nil) {
                                                   mError = error;
                                                   LogNSError("Error", error);
                                               }
                                               if (responsesNeeded == 0) {
                                                   SetCommandExitStatus(mError);
                                               }
                                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestListStructArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>>
        mComplex_Arg1;
};

/*
 * Command TestListInt8UArgumentRequest
 */
class TestClusterTestListInt8UArgumentRequest : public ClusterCommand {
public:
    TestClusterTestListInt8UArgumentRequest()
        : ClusterCommand("test-list-int8uargument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestListInt8UArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg1) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedChar:entry_0];
                [array_0 addObject:newElement_0];
            }
            params.arg1 = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testListInt8UArgumentRequestWithParams:params
                                          completionHandler:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                              NSError * _Nullable error) {
                                              NSLog(@"Values: %@", values);
                                              responsesNeeded--;
                                              if (error != nil) {
                                                  mError = error;
                                                  LogNSError("Error", error);
                                              }
                                              if (responsesNeeded == 0) {
                                                  SetCommandExitStatus(mError);
                                              }
                                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestListInt8UArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const uint8_t>> mComplex_Arg1;
};

/*
 * Command TestNestedStructListArgumentRequest
 */
class TestClusterTestNestedStructListArgumentRequest : public ClusterCommand {
public:
    TestClusterTestNestedStructListArgumentRequest()
        : ClusterCommand("test-nested-struct-list-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestNestedStructListArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRTestClusterClusterNestedStructList new];
        params.arg1.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.a];
        params.arg1.b = [NSNumber numberWithBool:mRequest.arg1.b];
        params.arg1.c = [MTRTestClusterClusterSimpleStruct new];
        params.arg1.c.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.c.a];
        params.arg1.c.b = [NSNumber numberWithBool:mRequest.arg1.c.b];
        params.arg1.c.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg1.c.c)];
        params.arg1.c.d = [NSData dataWithBytes:mRequest.arg1.c.d.data() length:mRequest.arg1.c.d.size()];
        params.arg1.c.e = [[NSString alloc] initWithBytes:mRequest.arg1.c.e.data()
                                                   length:mRequest.arg1.c.e.size()
                                                 encoding:NSUTF8StringEncoding];
        params.arg1.c.f = [NSNumber numberWithUnsignedChar:mRequest.arg1.c.f.Raw()];
        params.arg1.c.g = [NSNumber numberWithFloat:mRequest.arg1.c.g];
        params.arg1.c.h = [NSNumber numberWithDouble:mRequest.arg1.c.h];
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.arg1.d) {
                MTRTestClusterClusterSimpleStruct * newElement_1;
                newElement_1 = [MTRTestClusterClusterSimpleStruct new];
                newElement_1.a = [NSNumber numberWithUnsignedChar:entry_1.a];
                newElement_1.b = [NSNumber numberWithBool:entry_1.b];
                newElement_1.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_1.c)];
                newElement_1.d = [NSData dataWithBytes:entry_1.d.data() length:entry_1.d.size()];
                newElement_1.e = [[NSString alloc] initWithBytes:entry_1.e.data()
                                                          length:entry_1.e.size()
                                                        encoding:NSUTF8StringEncoding];
                newElement_1.f = [NSNumber numberWithUnsignedChar:entry_1.f.Raw()];
                newElement_1.g = [NSNumber numberWithFloat:entry_1.g];
                newElement_1.h = [NSNumber numberWithDouble:entry_1.h];
                [array_1 addObject:newElement_1];
            }
            params.arg1.d = array_1;
        }
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.arg1.e) {
                NSNumber * newElement_1;
                newElement_1 = [NSNumber numberWithUnsignedInt:entry_1];
                [array_1 addObject:newElement_1];
            }
            params.arg1.e = array_1;
        }
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.arg1.f) {
                NSData * newElement_1;
                newElement_1 = [NSData dataWithBytes:entry_1.data() length:entry_1.size()];
                [array_1 addObject:newElement_1];
            }
            params.arg1.f = array_1;
        }
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.arg1.g) {
                NSNumber * newElement_1;
                newElement_1 = [NSNumber numberWithUnsignedChar:entry_1];
                [array_1 addObject:newElement_1];
            }
            params.arg1.g = array_1;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testNestedStructListArgumentRequestWithParams:params
                                                 completionHandler:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                                     NSError * _Nullable error) {
                                                     NSLog(@"Values: %@", values);
                                                     responsesNeeded--;
                                                     if (error != nil) {
                                                         mError = error;
                                                         LogNSError("Error", error);
                                                     }
                                                     if (responsesNeeded == 0) {
                                                         SetCommandExitStatus(mError);
                                                     }
                                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestNestedStructListArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::TestCluster::Structs::NestedStructList::Type> mComplex_Arg1;
};

/*
 * Command TestListNestedStructListArgumentRequest
 */
class TestClusterTestListNestedStructListArgumentRequest : public ClusterCommand {
public:
    TestClusterTestListNestedStructListArgumentRequest()
        : ClusterCommand("test-list-nested-struct-list-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestListNestedStructListArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg1) {
                MTRTestClusterClusterNestedStructList * newElement_0;
                newElement_0 = [MTRTestClusterClusterNestedStructList new];
                newElement_0.a = [NSNumber numberWithUnsignedChar:entry_0.a];
                newElement_0.b = [NSNumber numberWithBool:entry_0.b];
                newElement_0.c = [MTRTestClusterClusterSimpleStruct new];
                newElement_0.c.a = [NSNumber numberWithUnsignedChar:entry_0.c.a];
                newElement_0.c.b = [NSNumber numberWithBool:entry_0.c.b];
                newElement_0.c.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.c.c)];
                newElement_0.c.d = [NSData dataWithBytes:entry_0.c.d.data() length:entry_0.c.d.size()];
                newElement_0.c.e = [[NSString alloc] initWithBytes:entry_0.c.e.data()
                                                            length:entry_0.c.e.size()
                                                          encoding:NSUTF8StringEncoding];
                newElement_0.c.f = [NSNumber numberWithUnsignedChar:entry_0.c.f.Raw()];
                newElement_0.c.g = [NSNumber numberWithFloat:entry_0.c.g];
                newElement_0.c.h = [NSNumber numberWithDouble:entry_0.c.h];
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.d) {
                        MTRTestClusterClusterSimpleStruct * newElement_2;
                        newElement_2 = [MTRTestClusterClusterSimpleStruct new];
                        newElement_2.a = [NSNumber numberWithUnsignedChar:entry_2.a];
                        newElement_2.b = [NSNumber numberWithBool:entry_2.b];
                        newElement_2.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_2.c)];
                        newElement_2.d = [NSData dataWithBytes:entry_2.d.data() length:entry_2.d.size()];
                        newElement_2.e = [[NSString alloc] initWithBytes:entry_2.e.data()
                                                                  length:entry_2.e.size()
                                                                encoding:NSUTF8StringEncoding];
                        newElement_2.f = [NSNumber numberWithUnsignedChar:entry_2.f.Raw()];
                        newElement_2.g = [NSNumber numberWithFloat:entry_2.g];
                        newElement_2.h = [NSNumber numberWithDouble:entry_2.h];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.d = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.e) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedInt:entry_2];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.e = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.f) {
                        NSData * newElement_2;
                        newElement_2 = [NSData dataWithBytes:entry_2.data() length:entry_2.size()];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.f = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.g) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedChar:entry_2];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.g = array_2;
                }
                [array_0 addObject:newElement_0];
            }
            params.arg1 = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testListNestedStructListArgumentRequestWithParams:params
                                                completionHandler:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                                    NSError * _Nullable error) {
                                                    NSLog(@"Values: %@", values);
                                                    responsesNeeded--;
                                                    if (error != nil) {
                                                        mError = error;
                                                        LogNSError("Error", error);
                                                    }
                                                    if (responsesNeeded == 0) {
                                                        SetCommandExitStatus(mError);
                                                    }
                                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestListNestedStructListArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::NestedStructList::Type>>
        mComplex_Arg1;
};

/*
 * Command TestListInt8UReverseRequest
 */
class TestClusterTestListInt8UReverseRequest : public ClusterCommand {
public:
    TestClusterTestListInt8UReverseRequest()
        : ClusterCommand("test-list-int8ureverse-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestListInt8UReverseRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg1) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedChar:entry_0];
                [array_0 addObject:newElement_0];
            }
            params.arg1 = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testListInt8UReverseRequestWithParams:params
                                    completionHandler:^(MTRTestClusterClusterTestListInt8UReverseResponseParams * _Nullable values,
                                        NSError * _Nullable error) {
                                        NSLog(@"Values: %@", values);
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestListInt8UReverseRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const uint8_t>> mComplex_Arg1;
};

/*
 * Command TestEnumsRequest
 */
class TestClusterTestEnumsRequest : public ClusterCommand {
public:
    TestClusterTestEnumsRequest()
        : ClusterCommand("test-enums-request")
    {
        AddArgument("Arg1", 0, UINT16_MAX, &mRequest.arg1);
        AddArgument("Arg2", 0, UINT8_MAX, &mRequest.arg2);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestEnumsRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [NSNumber numberWithUnsignedShort:chip::to_underlying(mRequest.arg1)];
        params.arg2 = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg2)];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testEnumsRequestWithParams:params
                              completionHandler:^(
                                  MTRTestClusterClusterTestEnumsResponseParams * _Nullable values, NSError * _Nullable error) {
                                  NSLog(@"Values: %@", values);
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestEnumsRequest::Type mRequest;
};

/*
 * Command TestNullableOptionalRequest
 */
class TestClusterTestNullableOptionalRequest : public ClusterCommand {
public:
    TestClusterTestNullableOptionalRequest()
        : ClusterCommand("test-nullable-optional-request")
    {
        AddArgument("Arg1", 0, UINT8_MAX, &mRequest.arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestNullableOptionalRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.arg1.HasValue()) {
            if (mRequest.arg1.Value().IsNull()) {
                params.arg1 = nil;
            } else {
                params.arg1 = [NSNumber numberWithUnsignedChar:mRequest.arg1.Value().Value()];
            }
        } else {
            params.arg1 = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testNullableOptionalRequestWithParams:params
                                    completionHandler:^(MTRTestClusterClusterTestNullableOptionalResponseParams * _Nullable values,
                                        NSError * _Nullable error) {
                                        NSLog(@"Values: %@", values);
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestNullableOptionalRequest::Type mRequest;
};

/*
 * Command TestComplexNullableOptionalRequest
 */
class TestClusterTestComplexNullableOptionalRequest : public ClusterCommand {
public:
    TestClusterTestComplexNullableOptionalRequest()
        : ClusterCommand("test-complex-nullable-optional-request")
        , mComplex_NullableStruct(&mRequest.nullableStruct)
        , mComplex_OptionalStruct(&mRequest.optionalStruct)
        , mComplex_NullableOptionalStruct(&mRequest.nullableOptionalStruct)
        , mComplex_NullableList(&mRequest.nullableList)
        , mComplex_OptionalList(&mRequest.optionalList)
        , mComplex_NullableOptionalList(&mRequest.nullableOptionalList)
    {
        AddArgument("NullableInt", 0, UINT16_MAX, &mRequest.nullableInt);
        AddArgument("OptionalInt", 0, UINT16_MAX, &mRequest.optionalInt);
        AddArgument("NullableOptionalInt", 0, UINT16_MAX, &mRequest.nullableOptionalInt);
        AddArgument("NullableString", &mRequest.nullableString);
        AddArgument("OptionalString", &mRequest.optionalString);
        AddArgument("NullableOptionalString", &mRequest.nullableOptionalString);
        AddArgument("NullableStruct", &mComplex_NullableStruct);
        AddArgument("OptionalStruct", &mComplex_OptionalStruct);
        AddArgument("NullableOptionalStruct", &mComplex_NullableOptionalStruct);
        AddArgument("NullableList", &mComplex_NullableList);
        AddArgument("OptionalList", &mComplex_OptionalList);
        AddArgument("NullableOptionalList", &mComplex_NullableOptionalList);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestComplexNullableOptionalRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.nullableInt.IsNull()) {
            params.nullableInt = nil;
        } else {
            params.nullableInt = [NSNumber numberWithUnsignedShort:mRequest.nullableInt.Value()];
        }
        if (mRequest.optionalInt.HasValue()) {
            params.optionalInt = [NSNumber numberWithUnsignedShort:mRequest.optionalInt.Value()];
        } else {
            params.optionalInt = nil;
        }
        if (mRequest.nullableOptionalInt.HasValue()) {
            if (mRequest.nullableOptionalInt.Value().IsNull()) {
                params.nullableOptionalInt = nil;
            } else {
                params.nullableOptionalInt = [NSNumber numberWithUnsignedShort:mRequest.nullableOptionalInt.Value().Value()];
            }
        } else {
            params.nullableOptionalInt = nil;
        }
        if (mRequest.nullableString.IsNull()) {
            params.nullableString = nil;
        } else {
            params.nullableString = [[NSString alloc] initWithBytes:mRequest.nullableString.Value().data()
                                                             length:mRequest.nullableString.Value().size()
                                                           encoding:NSUTF8StringEncoding];
        }
        if (mRequest.optionalString.HasValue()) {
            params.optionalString = [[NSString alloc] initWithBytes:mRequest.optionalString.Value().data()
                                                             length:mRequest.optionalString.Value().size()
                                                           encoding:NSUTF8StringEncoding];
        } else {
            params.optionalString = nil;
        }
        if (mRequest.nullableOptionalString.HasValue()) {
            if (mRequest.nullableOptionalString.Value().IsNull()) {
                params.nullableOptionalString = nil;
            } else {
                params.nullableOptionalString =
                    [[NSString alloc] initWithBytes:mRequest.nullableOptionalString.Value().Value().data()
                                             length:mRequest.nullableOptionalString.Value().Value().size()
                                           encoding:NSUTF8StringEncoding];
            }
        } else {
            params.nullableOptionalString = nil;
        }
        if (mRequest.nullableStruct.IsNull()) {
            params.nullableStruct = nil;
        } else {
            params.nullableStruct = [MTRTestClusterClusterSimpleStruct new];
            params.nullableStruct.a = [NSNumber numberWithUnsignedChar:mRequest.nullableStruct.Value().a];
            params.nullableStruct.b = [NSNumber numberWithBool:mRequest.nullableStruct.Value().b];
            params.nullableStruct.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.nullableStruct.Value().c)];
            params.nullableStruct.d = [NSData dataWithBytes:mRequest.nullableStruct.Value().d.data()
                                                     length:mRequest.nullableStruct.Value().d.size()];
            params.nullableStruct.e = [[NSString alloc] initWithBytes:mRequest.nullableStruct.Value().e.data()
                                                               length:mRequest.nullableStruct.Value().e.size()
                                                             encoding:NSUTF8StringEncoding];
            params.nullableStruct.f = [NSNumber numberWithUnsignedChar:mRequest.nullableStruct.Value().f.Raw()];
            params.nullableStruct.g = [NSNumber numberWithFloat:mRequest.nullableStruct.Value().g];
            params.nullableStruct.h = [NSNumber numberWithDouble:mRequest.nullableStruct.Value().h];
        }
        if (mRequest.optionalStruct.HasValue()) {
            params.optionalStruct = [MTRTestClusterClusterSimpleStruct new];
            params.optionalStruct.a = [NSNumber numberWithUnsignedChar:mRequest.optionalStruct.Value().a];
            params.optionalStruct.b = [NSNumber numberWithBool:mRequest.optionalStruct.Value().b];
            params.optionalStruct.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.optionalStruct.Value().c)];
            params.optionalStruct.d = [NSData dataWithBytes:mRequest.optionalStruct.Value().d.data()
                                                     length:mRequest.optionalStruct.Value().d.size()];
            params.optionalStruct.e = [[NSString alloc] initWithBytes:mRequest.optionalStruct.Value().e.data()
                                                               length:mRequest.optionalStruct.Value().e.size()
                                                             encoding:NSUTF8StringEncoding];
            params.optionalStruct.f = [NSNumber numberWithUnsignedChar:mRequest.optionalStruct.Value().f.Raw()];
            params.optionalStruct.g = [NSNumber numberWithFloat:mRequest.optionalStruct.Value().g];
            params.optionalStruct.h = [NSNumber numberWithDouble:mRequest.optionalStruct.Value().h];
        } else {
            params.optionalStruct = nil;
        }
        if (mRequest.nullableOptionalStruct.HasValue()) {
            if (mRequest.nullableOptionalStruct.Value().IsNull()) {
                params.nullableOptionalStruct = nil;
            } else {
                params.nullableOptionalStruct = [MTRTestClusterClusterSimpleStruct new];
                params.nullableOptionalStruct.a =
                    [NSNumber numberWithUnsignedChar:mRequest.nullableOptionalStruct.Value().Value().a];
                params.nullableOptionalStruct.b = [NSNumber numberWithBool:mRequest.nullableOptionalStruct.Value().Value().b];
                params.nullableOptionalStruct.c =
                    [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.nullableOptionalStruct.Value().Value().c)];
                params.nullableOptionalStruct.d = [NSData dataWithBytes:mRequest.nullableOptionalStruct.Value().Value().d.data()
                                                                 length:mRequest.nullableOptionalStruct.Value().Value().d.size()];
                params.nullableOptionalStruct.e =
                    [[NSString alloc] initWithBytes:mRequest.nullableOptionalStruct.Value().Value().e.data()
                                             length:mRequest.nullableOptionalStruct.Value().Value().e.size()
                                           encoding:NSUTF8StringEncoding];
                params.nullableOptionalStruct.f =
                    [NSNumber numberWithUnsignedChar:mRequest.nullableOptionalStruct.Value().Value().f.Raw()];
                params.nullableOptionalStruct.g = [NSNumber numberWithFloat:mRequest.nullableOptionalStruct.Value().Value().g];
                params.nullableOptionalStruct.h = [NSNumber numberWithDouble:mRequest.nullableOptionalStruct.Value().Value().h];
            }
        } else {
            params.nullableOptionalStruct = nil;
        }
        if (mRequest.nullableList.IsNull()) {
            params.nullableList = nil;
        } else {
            { // Scope for our temporary variables
                auto * array_1 = [NSMutableArray new];
                for (auto & entry_1 : mRequest.nullableList.Value()) {
                    NSNumber * newElement_1;
                    newElement_1 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_1)];
                    [array_1 addObject:newElement_1];
                }
                params.nullableList = array_1;
            }
        }
        if (mRequest.optionalList.HasValue()) {
            { // Scope for our temporary variables
                auto * array_1 = [NSMutableArray new];
                for (auto & entry_1 : mRequest.optionalList.Value()) {
                    NSNumber * newElement_1;
                    newElement_1 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_1)];
                    [array_1 addObject:newElement_1];
                }
                params.optionalList = array_1;
            }
        } else {
            params.optionalList = nil;
        }
        if (mRequest.nullableOptionalList.HasValue()) {
            if (mRequest.nullableOptionalList.Value().IsNull()) {
                params.nullableOptionalList = nil;
            } else {
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : mRequest.nullableOptionalList.Value().Value()) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_2)];
                        [array_2 addObject:newElement_2];
                    }
                    params.nullableOptionalList = array_2;
                }
            }
        } else {
            params.nullableOptionalList = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testComplexNullableOptionalRequestWithParams:params
                                           completionHandler:^(
                                               MTRTestClusterClusterTestComplexNullableOptionalResponseParams * _Nullable values,
                                               NSError * _Nullable error) {
                                               NSLog(@"Values: %@", values);
                                               responsesNeeded--;
                                               if (error != nil) {
                                                   mError = error;
                                                   LogNSError("Error", error);
                                               }
                                               if (responsesNeeded == 0) {
                                                   SetCommandExitStatus(mError);
                                               }
                                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestComplexNullableOptionalRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::Nullable<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>>
        mComplex_NullableStruct;
    TypedComplexArgument<chip::Optional<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>> mComplex_OptionalStruct;
    TypedComplexArgument<
        chip::Optional<chip::app::DataModel::Nullable<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>>>
        mComplex_NullableOptionalStruct;
    TypedComplexArgument<
        chip::app::DataModel::Nullable<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::SimpleEnum>>>
        mComplex_NullableList;
    TypedComplexArgument<chip::Optional<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::SimpleEnum>>>
        mComplex_OptionalList;
    TypedComplexArgument<chip::Optional<
        chip::app::DataModel::Nullable<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::SimpleEnum>>>>
        mComplex_NullableOptionalList;
};

/*
 * Command SimpleStructEchoRequest
 */
class TestClusterSimpleStructEchoRequest : public ClusterCommand {
public:
    TestClusterSimpleStructEchoRequest()
        : ClusterCommand("simple-struct-echo-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterSimpleStructEchoRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRTestClusterClusterSimpleStruct new];
        params.arg1.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.a];
        params.arg1.b = [NSNumber numberWithBool:mRequest.arg1.b];
        params.arg1.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg1.c)];
        params.arg1.d = [NSData dataWithBytes:mRequest.arg1.d.data() length:mRequest.arg1.d.size()];
        params.arg1.e = [[NSString alloc] initWithBytes:mRequest.arg1.e.data()
                                                 length:mRequest.arg1.e.size()
                                               encoding:NSUTF8StringEncoding];
        params.arg1.f = [NSNumber numberWithUnsignedChar:mRequest.arg1.f.Raw()];
        params.arg1.g = [NSNumber numberWithFloat:mRequest.arg1.g];
        params.arg1.h = [NSNumber numberWithDouble:mRequest.arg1.h];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster simpleStructEchoRequestWithParams:params
                                     completionHandler:^(MTRTestClusterClusterSimpleStructResponseParams * _Nullable values,
                                         NSError * _Nullable error) {
                                         NSLog(@"Values: %@", values);
                                         responsesNeeded--;
                                         if (error != nil) {
                                             mError = error;
                                             LogNSError("Error", error);
                                         }
                                         if (responsesNeeded == 0) {
                                             SetCommandExitStatus(mError);
                                         }
                                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::SimpleStructEchoRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type> mComplex_Arg1;
};

/*
 * Command TimedInvokeRequest
 */
class TestClusterTimedInvokeRequest : public ClusterCommand {
public:
    TestClusterTimedInvokeRequest()
        : ClusterCommand("timed-invoke-request")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTimedInvokeRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster timedInvokeRequestWithParams:params
                                completionHandler:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command TestSimpleOptionalArgumentRequest
 */
class TestClusterTestSimpleOptionalArgumentRequest : public ClusterCommand {
public:
    TestClusterTestSimpleOptionalArgumentRequest()
        : ClusterCommand("test-simple-optional-argument-request")
    {
        AddArgument("Arg1", 0, 1, &mRequest.arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestSimpleOptionalArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.arg1.HasValue()) {
            params.arg1 = [NSNumber numberWithBool:mRequest.arg1.Value()];
        } else {
            params.arg1 = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testSimpleOptionalArgumentRequestWithParams:params
                                               completionHandler:^(NSError * _Nullable error) {
                                                   responsesNeeded--;
                                                   if (error != nil) {
                                                       mError = error;
                                                       LogNSError("Error", error);
                                                   }
                                                   if (responsesNeeded == 0) {
                                                       SetCommandExitStatus(mError);
                                                   }
                                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestSimpleOptionalArgumentRequest::Type mRequest;
};

/*
 * Command TestEmitTestEventRequest
 */
class TestClusterTestEmitTestEventRequest : public ClusterCommand {
public:
    TestClusterTestEmitTestEventRequest()
        : ClusterCommand("test-emit-test-event-request")
    {
        AddArgument("Arg1", 0, UINT8_MAX, &mRequest.arg1);
        AddArgument("Arg2", 0, UINT8_MAX, &mRequest.arg2);
        AddArgument("Arg3", 0, 1, &mRequest.arg3);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestEmitTestEventRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [NSNumber numberWithUnsignedChar:mRequest.arg1];
        params.arg2 = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg2)];
        params.arg3 = [NSNumber numberWithBool:mRequest.arg3];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testEmitTestEventRequestWithParams:params
                                      completionHandler:^(MTRTestClusterClusterTestEmitTestEventResponseParams * _Nullable values,
                                          NSError * _Nullable error) {
                                          NSLog(@"Values: %@", values);
                                          responsesNeeded--;
                                          if (error != nil) {
                                              mError = error;
                                              LogNSError("Error", error);
                                          }
                                          if (responsesNeeded == 0) {
                                              SetCommandExitStatus(mError);
                                          }
                                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestEmitTestEventRequest::Type mRequest;
};

/*
 * Command TestEmitTestFabricScopedEventRequest
 */
class TestClusterTestEmitTestFabricScopedEventRequest : public ClusterCommand {
public:
    TestClusterTestEmitTestFabricScopedEventRequest()
        : ClusterCommand("test-emit-test-fabric-scoped-event-request")
    {
        AddArgument("Arg1", 0, UINT8_MAX, &mRequest.arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestEmitTestFabricScopedEventRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [NSNumber numberWithUnsignedChar:mRequest.arg1];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testEmitTestFabricScopedEventRequestWithParams:params
                                             completionHandler:^(
                                                 MTRTestClusterClusterTestEmitTestFabricScopedEventResponseParams * _Nullable values,
                                                 NSError * _Nullable error) {
                                                 NSLog(@"Values: %@", values);
                                                 responsesNeeded--;
                                                 if (error != nil) {
                                                     mError = error;
                                                     LogNSError("Error", error);
                                                 }
                                                 if (responsesNeeded == 0) {
                                                     SetCommandExitStatus(mError);
                                                 }
                                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestEmitTestFabricScopedEventRequest::Type mRequest;
};

/*
 * Attribute Boolean
 */
class ReadTestClusterBoolean : public ReadAttribute {
public:
    ReadTestClusterBoolean()
        : ReadAttribute("boolean")
    {
    }

    ~ReadTestClusterBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBooleanWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Boolean response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Boolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterBoolean : public WriteAttribute {
public:
    WriteTestClusterBoolean()
        : WriteAttribute("boolean")
    {
        AddArgument("attr-name", "boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeBooleanWithValue:value
                                         params:params
                              completionHandler:^(NSError * _Nullable error) {
                                  if (error != nil) {
                                      LogNSError("TestCluster Boolean write Error", error);
                                  }
                                  SetCommandExitStatus(error);
                              }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterBoolean()
        : SubscribeAttribute("boolean")
    {
    }

    ~SubscribeAttributeTestClusterBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBooleanWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Boolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap8
 */
class ReadTestClusterBitmap8 : public ReadAttribute {
public:
    ReadTestClusterBitmap8()
        : ReadAttribute("bitmap8")
    {
    }

    ~ReadTestClusterBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBitmap8WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Bitmap8 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Bitmap8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterBitmap8 : public WriteAttribute {
public:
    WriteTestClusterBitmap8()
        : WriteAttribute("bitmap8")
    {
        AddArgument("attr-name", "bitmap8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeBitmap8WithValue:value
                                         params:params
                              completionHandler:^(NSError * _Nullable error) {
                                  if (error != nil) {
                                      LogNSError("TestCluster Bitmap8 write Error", error);
                                  }
                                  SetCommandExitStatus(error);
                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterBitmap8 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterBitmap8()
        : SubscribeAttribute("bitmap8")
    {
    }

    ~SubscribeAttributeTestClusterBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBitmap8WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Bitmap8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap16
 */
class ReadTestClusterBitmap16 : public ReadAttribute {
public:
    ReadTestClusterBitmap16()
        : ReadAttribute("bitmap16")
    {
    }

    ~ReadTestClusterBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBitmap16WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Bitmap16 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Bitmap16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterBitmap16 : public WriteAttribute {
public:
    WriteTestClusterBitmap16()
        : WriteAttribute("bitmap16")
    {
        AddArgument("attr-name", "bitmap16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBitmap16WithValue:value
                                          params:params
                               completionHandler:^(NSError * _Nullable error) {
                                   if (error != nil) {
                                       LogNSError("TestCluster Bitmap16 write Error", error);
                                   }
                                   SetCommandExitStatus(error);
                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterBitmap16 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterBitmap16()
        : SubscribeAttribute("bitmap16")
    {
    }

    ~SubscribeAttributeTestClusterBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBitmap16WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Bitmap16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap32
 */
class ReadTestClusterBitmap32 : public ReadAttribute {
public:
    ReadTestClusterBitmap32()
        : ReadAttribute("bitmap32")
    {
    }

    ~ReadTestClusterBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBitmap32WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Bitmap32 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Bitmap32 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterBitmap32 : public WriteAttribute {
public:
    WriteTestClusterBitmap32()
        : WriteAttribute("bitmap32")
    {
        AddArgument("attr-name", "bitmap32");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeBitmap32WithValue:value
                                          params:params
                               completionHandler:^(NSError * _Nullable error) {
                                   if (error != nil) {
                                       LogNSError("TestCluster Bitmap32 write Error", error);
                                   }
                                   SetCommandExitStatus(error);
                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterBitmap32 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterBitmap32()
        : SubscribeAttribute("bitmap32")
    {
    }

    ~SubscribeAttributeTestClusterBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBitmap32WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Bitmap32 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap64
 */
class ReadTestClusterBitmap64 : public ReadAttribute {
public:
    ReadTestClusterBitmap64()
        : ReadAttribute("bitmap64")
    {
    }

    ~ReadTestClusterBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeBitmap64WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Bitmap64 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Bitmap64 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterBitmap64 : public WriteAttribute {
public:
    WriteTestClusterBitmap64()
        : WriteAttribute("bitmap64")
    {
        AddArgument("attr-name", "bitmap64");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeBitmap64WithValue:value
                                          params:params
                               completionHandler:^(NSError * _Nullable error) {
                                   if (error != nil) {
                                       LogNSError("TestCluster Bitmap64 write Error", error);
                                   }
                                   SetCommandExitStatus(error);
                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterBitmap64 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterBitmap64()
        : SubscribeAttribute("bitmap64")
    {
    }

    ~SubscribeAttributeTestClusterBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeBitmap64WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Bitmap64 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int8u
 */
class ReadTestClusterInt8u : public ReadAttribute {
public:
    ReadTestClusterInt8u()
        : ReadAttribute("int8u")
    {
    }

    ~ReadTestClusterInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt8uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt8u : public WriteAttribute {
public:
    WriteTestClusterInt8u()
        : WriteAttribute("int8u")
    {
        AddArgument("attr-name", "int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeInt8uWithValue:value
                                       params:params
                            completionHandler:^(NSError * _Nullable error) {
                                if (error != nil) {
                                    LogNSError("TestCluster Int8u write Error", error);
                                }
                                SetCommandExitStatus(error);
                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt8u()
        : SubscribeAttribute("int8u")
    {
    }

    ~SubscribeAttributeTestClusterInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt8uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int16u
 */
class ReadTestClusterInt16u : public ReadAttribute {
public:
    ReadTestClusterInt16u()
        : ReadAttribute("int16u")
    {
    }

    ~ReadTestClusterInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt16uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int16u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt16u : public WriteAttribute {
public:
    WriteTestClusterInt16u()
        : WriteAttribute("int16u")
    {
        AddArgument("attr-name", "int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeInt16uWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int16u write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt16u()
        : SubscribeAttribute("int16u")
    {
    }

    ~SubscribeAttributeTestClusterInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt16uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int24u
 */
class ReadTestClusterInt24u : public ReadAttribute {
public:
    ReadTestClusterInt24u()
        : ReadAttribute("int24u")
    {
    }

    ~ReadTestClusterInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt24uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int24u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int24u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt24u : public WriteAttribute {
public:
    WriteTestClusterInt24u()
        : WriteAttribute("int24u")
    {
        AddArgument("attr-name", "int24u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeInt24uWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int24u write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterInt24u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt24u()
        : SubscribeAttribute("int24u")
    {
    }

    ~SubscribeAttributeTestClusterInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt24uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int24u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int32u
 */
class ReadTestClusterInt32u : public ReadAttribute {
public:
    ReadTestClusterInt32u()
        : ReadAttribute("int32u")
    {
    }

    ~ReadTestClusterInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt32uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int32u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int32u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt32u : public WriteAttribute {
public:
    WriteTestClusterInt32u()
        : WriteAttribute("int32u")
    {
        AddArgument("attr-name", "int32u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeInt32uWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int32u write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterInt32u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt32u()
        : SubscribeAttribute("int32u")
    {
    }

    ~SubscribeAttributeTestClusterInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt32uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int32u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int40u
 */
class ReadTestClusterInt40u : public ReadAttribute {
public:
    ReadTestClusterInt40u()
        : ReadAttribute("int40u")
    {
    }

    ~ReadTestClusterInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt40uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int40u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int40u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt40u : public WriteAttribute {
public:
    WriteTestClusterInt40u()
        : WriteAttribute("int40u")
    {
        AddArgument("attr-name", "int40u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt40uWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int40u write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterInt40u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt40u()
        : SubscribeAttribute("int40u")
    {
    }

    ~SubscribeAttributeTestClusterInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt40uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int40u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int48u
 */
class ReadTestClusterInt48u : public ReadAttribute {
public:
    ReadTestClusterInt48u()
        : ReadAttribute("int48u")
    {
    }

    ~ReadTestClusterInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt48uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int48u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int48u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt48u : public WriteAttribute {
public:
    WriteTestClusterInt48u()
        : WriteAttribute("int48u")
    {
        AddArgument("attr-name", "int48u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt48uWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int48u write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterInt48u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt48u()
        : SubscribeAttribute("int48u")
    {
    }

    ~SubscribeAttributeTestClusterInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt48uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int48u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int56u
 */
class ReadTestClusterInt56u : public ReadAttribute {
public:
    ReadTestClusterInt56u()
        : ReadAttribute("int56u")
    {
    }

    ~ReadTestClusterInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt56uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int56u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int56u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt56u : public WriteAttribute {
public:
    WriteTestClusterInt56u()
        : WriteAttribute("int56u")
    {
        AddArgument("attr-name", "int56u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt56uWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int56u write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterInt56u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt56u()
        : SubscribeAttribute("int56u")
    {
    }

    ~SubscribeAttributeTestClusterInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt56uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int56u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int64u
 */
class ReadTestClusterInt64u : public ReadAttribute {
public:
    ReadTestClusterInt64u()
        : ReadAttribute("int64u")
    {
    }

    ~ReadTestClusterInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt64uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int64u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int64u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt64u : public WriteAttribute {
public:
    WriteTestClusterInt64u()
        : WriteAttribute("int64u")
    {
        AddArgument("attr-name", "int64u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt64uWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int64u write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterInt64u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt64u()
        : SubscribeAttribute("int64u")
    {
    }

    ~SubscribeAttributeTestClusterInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt64uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int64u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int8s
 */
class ReadTestClusterInt8s : public ReadAttribute {
public:
    ReadTestClusterInt8s()
        : ReadAttribute("int8s")
    {
    }

    ~ReadTestClusterInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt8sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int8s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt8s : public WriteAttribute {
public:
    WriteTestClusterInt8s()
        : WriteAttribute("int8s")
    {
        AddArgument("attr-name", "int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeInt8sWithValue:value
                                       params:params
                            completionHandler:^(NSError * _Nullable error) {
                                if (error != nil) {
                                    LogNSError("TestCluster Int8s write Error", error);
                                }
                                SetCommandExitStatus(error);
                            }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeTestClusterInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt8s()
        : SubscribeAttribute("int8s")
    {
    }

    ~SubscribeAttributeTestClusterInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt8sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int16s
 */
class ReadTestClusterInt16s : public ReadAttribute {
public:
    ReadTestClusterInt16s()
        : ReadAttribute("int16s")
    {
    }

    ~ReadTestClusterInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt16sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int16s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt16s : public WriteAttribute {
public:
    WriteTestClusterInt16s()
        : WriteAttribute("int16s")
    {
        AddArgument("attr-name", "int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeInt16sWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int16s write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeTestClusterInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt16s()
        : SubscribeAttribute("int16s")
    {
    }

    ~SubscribeAttributeTestClusterInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt16sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int24s
 */
class ReadTestClusterInt24s : public ReadAttribute {
public:
    ReadTestClusterInt24s()
        : ReadAttribute("int24s")
    {
    }

    ~ReadTestClusterInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt24sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int24s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int24s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt24s : public WriteAttribute {
public:
    WriteTestClusterInt24s()
        : WriteAttribute("int24s")
    {
        AddArgument("attr-name", "int24s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeInt24sWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int24s write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeTestClusterInt24s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt24s()
        : SubscribeAttribute("int24s")
    {
    }

    ~SubscribeAttributeTestClusterInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt24sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int24s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int32s
 */
class ReadTestClusterInt32s : public ReadAttribute {
public:
    ReadTestClusterInt32s()
        : ReadAttribute("int32s")
    {
    }

    ~ReadTestClusterInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt32sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int32s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int32s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt32s : public WriteAttribute {
public:
    WriteTestClusterInt32s()
        : WriteAttribute("int32s")
    {
        AddArgument("attr-name", "int32s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeInt32sWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int32s write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeTestClusterInt32s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt32s()
        : SubscribeAttribute("int32s")
    {
    }

    ~SubscribeAttributeTestClusterInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt32sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int32s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int40s
 */
class ReadTestClusterInt40s : public ReadAttribute {
public:
    ReadTestClusterInt40s()
        : ReadAttribute("int40s")
    {
    }

    ~ReadTestClusterInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt40sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int40s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int40s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt40s : public WriteAttribute {
public:
    WriteTestClusterInt40s()
        : WriteAttribute("int40s")
    {
        AddArgument("attr-name", "int40s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt40sWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int40s write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterInt40s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt40s()
        : SubscribeAttribute("int40s")
    {
    }

    ~SubscribeAttributeTestClusterInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt40sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int40s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int48s
 */
class ReadTestClusterInt48s : public ReadAttribute {
public:
    ReadTestClusterInt48s()
        : ReadAttribute("int48s")
    {
    }

    ~ReadTestClusterInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt48sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int48s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int48s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt48s : public WriteAttribute {
public:
    WriteTestClusterInt48s()
        : WriteAttribute("int48s")
    {
        AddArgument("attr-name", "int48s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt48sWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int48s write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterInt48s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt48s()
        : SubscribeAttribute("int48s")
    {
    }

    ~SubscribeAttributeTestClusterInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt48sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int48s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int56s
 */
class ReadTestClusterInt56s : public ReadAttribute {
public:
    ReadTestClusterInt56s()
        : ReadAttribute("int56s")
    {
    }

    ~ReadTestClusterInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt56sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int56s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int56s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt56s : public WriteAttribute {
public:
    WriteTestClusterInt56s()
        : WriteAttribute("int56s")
    {
        AddArgument("attr-name", "int56s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt56sWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int56s write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterInt56s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt56s()
        : SubscribeAttribute("int56s")
    {
    }

    ~SubscribeAttributeTestClusterInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt56sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int56s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int64s
 */
class ReadTestClusterInt64s : public ReadAttribute {
public:
    ReadTestClusterInt64s()
        : ReadAttribute("int64s")
    {
    }

    ~ReadTestClusterInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt64sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int64s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int64s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt64s : public WriteAttribute {
public:
    WriteTestClusterInt64s()
        : WriteAttribute("int64s")
    {
        AddArgument("attr-name", "int64s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt64sWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Int64s write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterInt64s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt64s()
        : SubscribeAttribute("int64s")
    {
    }

    ~SubscribeAttributeTestClusterInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeInt64sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int64s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Enum8
 */
class ReadTestClusterEnum8 : public ReadAttribute {
public:
    ReadTestClusterEnum8()
        : ReadAttribute("enum8")
    {
    }

    ~ReadTestClusterEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeEnum8WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Enum8 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Enum8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterEnum8 : public WriteAttribute {
public:
    WriteTestClusterEnum8()
        : WriteAttribute("enum8")
    {
        AddArgument("attr-name", "enum8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeEnum8WithValue:value
                                       params:params
                            completionHandler:^(NSError * _Nullable error) {
                                if (error != nil) {
                                    LogNSError("TestCluster Enum8 write Error", error);
                                }
                                SetCommandExitStatus(error);
                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterEnum8 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterEnum8()
        : SubscribeAttribute("enum8")
    {
    }

    ~SubscribeAttributeTestClusterEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEnum8WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Enum8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Enum16
 */
class ReadTestClusterEnum16 : public ReadAttribute {
public:
    ReadTestClusterEnum16()
        : ReadAttribute("enum16")
    {
    }

    ~ReadTestClusterEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeEnum16WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Enum16 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Enum16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterEnum16 : public WriteAttribute {
public:
    WriteTestClusterEnum16()
        : WriteAttribute("enum16")
    {
        AddArgument("attr-name", "enum16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeEnum16WithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster Enum16 write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterEnum16 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterEnum16()
        : SubscribeAttribute("enum16")
    {
    }

    ~SubscribeAttributeTestClusterEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEnum16WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Enum16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FloatSingle
 */
class ReadTestClusterFloatSingle : public ReadAttribute {
public:
    ReadTestClusterFloatSingle()
        : ReadAttribute("float-single")
    {
    }

    ~ReadTestClusterFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeFloatSingleWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.FloatSingle response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster FloatSingle read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterFloatSingle : public WriteAttribute {
public:
    WriteTestClusterFloatSingle()
        : WriteAttribute("float-single")
    {
        AddArgument("attr-name", "float-single");
        AddArgument("attr-value", -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithFloat:mValue];

        [cluster writeAttributeFloatSingleWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("TestCluster FloatSingle write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    float mValue;
};

class SubscribeAttributeTestClusterFloatSingle : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterFloatSingle()
        : SubscribeAttribute("float-single")
    {
    }

    ~SubscribeAttributeTestClusterFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFloatSingleWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.FloatSingle response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FloatDouble
 */
class ReadTestClusterFloatDouble : public ReadAttribute {
public:
    ReadTestClusterFloatDouble()
        : ReadAttribute("float-double")
    {
    }

    ~ReadTestClusterFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeFloatDoubleWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.FloatDouble response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster FloatDouble read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterFloatDouble : public WriteAttribute {
public:
    WriteTestClusterFloatDouble()
        : WriteAttribute("float-double")
    {
        AddArgument("attr-name", "float-double");
        AddArgument("attr-value", -std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity(), &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithDouble:mValue];

        [cluster writeAttributeFloatDoubleWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("TestCluster FloatDouble write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    double mValue;
};

class SubscribeAttributeTestClusterFloatDouble : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterFloatDouble()
        : SubscribeAttribute("float-double")
    {
    }

    ~SubscribeAttributeTestClusterFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFloatDoubleWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.FloatDouble response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OctetString
 */
class ReadTestClusterOctetString : public ReadAttribute {
public:
    ReadTestClusterOctetString()
        : ReadAttribute("octet-string")
    {
    }

    ~ReadTestClusterOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeOctetStringWithCompletionHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.OctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster OctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterOctetString : public WriteAttribute {
public:
    WriteTestClusterOctetString()
        : WriteAttribute("octet-string")
    {
        AddArgument("attr-name", "octet-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSData * _Nonnull value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()];

        [cluster writeAttributeOctetStringWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("TestCluster OctetString write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterOctetString()
        : SubscribeAttribute("octet-string")
    {
    }

    ~SubscribeAttributeTestClusterOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeOctetStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.OctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListInt8u
 */
class ReadTestClusterListInt8u : public ReadAttribute {
public:
    ReadTestClusterListInt8u()
        : ReadAttribute("list-int8u")
    {
    }

    ~ReadTestClusterListInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeListInt8uWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ListInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ListInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListInt8u : public WriteAttribute {
public:
    WriteTestClusterListInt8u()
        : WriteAttribute("list-int8u")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-int8u");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedChar:entry_0];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListInt8uWithValue:value
                                           params:params
                                completionHandler:^(NSError * _Nullable error) {
                                    if (error != nil) {
                                        LogNSError("TestCluster ListInt8u write Error", error);
                                    }
                                    SetCommandExitStatus(error);
                                }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const uint8_t> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const uint8_t>> mComplex;
};

class SubscribeAttributeTestClusterListInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListInt8u()
        : SubscribeAttribute("list-int8u")
    {
    }

    ~SubscribeAttributeTestClusterListInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeListInt8uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListOctetString
 */
class ReadTestClusterListOctetString : public ReadAttribute {
public:
    ReadTestClusterListOctetString()
        : ReadAttribute("list-octet-string")
    {
    }

    ~ReadTestClusterListOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeListOctetStringWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ListOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ListOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListOctetString : public WriteAttribute {
public:
    WriteTestClusterListOctetString()
        : WriteAttribute("list-octet-string")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-octet-string");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                NSData * newElement_0;
                newElement_0 = [NSData dataWithBytes:entry_0.data() length:entry_0.size()];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListOctetStringWithValue:value
                                                 params:params
                                      completionHandler:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("TestCluster ListOctetString write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::ByteSpan> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::ByteSpan>> mComplex;
};

class SubscribeAttributeTestClusterListOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListOctetString()
        : SubscribeAttribute("list-octet-string")
    {
    }

    ~SubscribeAttributeTestClusterListOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeListOctetStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListStructOctetString
 */
class ReadTestClusterListStructOctetString : public ReadAttribute {
public:
    ReadTestClusterListStructOctetString()
        : ReadAttribute("list-struct-octet-string")
    {
    }

    ~ReadTestClusterListStructOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeListStructOctetStringWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ListStructOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ListStructOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListStructOctetString : public WriteAttribute {
public:
    WriteTestClusterListStructOctetString()
        : WriteAttribute("list-struct-octet-string")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-struct-octet-string");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListStructOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRTestClusterClusterTestListStructOctet * newElement_0;
                newElement_0 = [MTRTestClusterClusterTestListStructOctet new];
                newElement_0.member1 = [NSNumber numberWithUnsignedLongLong:entry_0.member1];
                newElement_0.member2 = [NSData dataWithBytes:entry_0.member2.data() length:entry_0.member2.size()];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListStructOctetStringWithValue:value
                                                       params:params
                                            completionHandler:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster ListStructOctetString write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::TestListStructOctet::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::TestListStructOctet::Type>>
        mComplex;
};

class SubscribeAttributeTestClusterListStructOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListStructOctetString()
        : SubscribeAttribute("list-struct-octet-string")
    {
    }

    ~SubscribeAttributeTestClusterListStructOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeListStructOctetStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListStructOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LongOctetString
 */
class ReadTestClusterLongOctetString : public ReadAttribute {
public:
    ReadTestClusterLongOctetString()
        : ReadAttribute("long-octet-string")
    {
    }

    ~ReadTestClusterLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeLongOctetStringWithCompletionHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.LongOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster LongOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterLongOctetString : public WriteAttribute {
public:
    WriteTestClusterLongOctetString()
        : WriteAttribute("long-octet-string")
    {
        AddArgument("attr-name", "long-octet-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSData * _Nonnull value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()];

        [cluster writeAttributeLongOctetStringWithValue:value
                                                 params:params
                                      completionHandler:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("TestCluster LongOctetString write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterLongOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterLongOctetString()
        : SubscribeAttribute("long-octet-string")
    {
    }

    ~SubscribeAttributeTestClusterLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLongOctetStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.LongOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CharString
 */
class ReadTestClusterCharString : public ReadAttribute {
public:
    ReadTestClusterCharString()
        : ReadAttribute("char-string")
    {
    }

    ~ReadTestClusterCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeCharStringWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.CharString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster CharString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterCharString : public WriteAttribute {
public:
    WriteTestClusterCharString()
        : WriteAttribute("char-string")
    {
        AddArgument("attr-name", "char-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeCharStringWithValue:value
                                            params:params
                                 completionHandler:^(NSError * _Nullable error) {
                                     if (error != nil) {
                                         LogNSError("TestCluster CharString write Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterCharString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterCharString()
        : SubscribeAttribute("char-string")
    {
    }

    ~SubscribeAttributeTestClusterCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeCharStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.CharString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LongCharString
 */
class ReadTestClusterLongCharString : public ReadAttribute {
public:
    ReadTestClusterLongCharString()
        : ReadAttribute("long-char-string")
    {
    }

    ~ReadTestClusterLongCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeLongCharStringWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.LongCharString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster LongCharString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterLongCharString : public WriteAttribute {
public:
    WriteTestClusterLongCharString()
        : WriteAttribute("long-char-string")
    {
        AddArgument("attr-name", "long-char-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterLongCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeLongCharStringWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster LongCharString write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterLongCharString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterLongCharString()
        : SubscribeAttribute("long-char-string")
    {
    }

    ~SubscribeAttributeTestClusterLongCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeLongCharStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.LongCharString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EpochUs
 */
class ReadTestClusterEpochUs : public ReadAttribute {
public:
    ReadTestClusterEpochUs()
        : ReadAttribute("epoch-us")
    {
    }

    ~ReadTestClusterEpochUs() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeEpochUsWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.EpochUs response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster EpochUs read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterEpochUs : public WriteAttribute {
public:
    WriteTestClusterEpochUs()
        : WriteAttribute("epoch-us")
    {
        AddArgument("attr-name", "epoch-us");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterEpochUs() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeEpochUsWithValue:value
                                         params:params
                              completionHandler:^(NSError * _Nullable error) {
                                  if (error != nil) {
                                      LogNSError("TestCluster EpochUs write Error", error);
                                  }
                                  SetCommandExitStatus(error);
                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterEpochUs : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterEpochUs()
        : SubscribeAttribute("epoch-us")
    {
    }

    ~SubscribeAttributeTestClusterEpochUs() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEpochUsWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.EpochUs response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EpochS
 */
class ReadTestClusterEpochS : public ReadAttribute {
public:
    ReadTestClusterEpochS()
        : ReadAttribute("epoch-s")
    {
    }

    ~ReadTestClusterEpochS() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeEpochSWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.EpochS response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster EpochS read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterEpochS : public WriteAttribute {
public:
    WriteTestClusterEpochS()
        : WriteAttribute("epoch-s")
    {
        AddArgument("attr-name", "epoch-s");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterEpochS() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeEpochSWithValue:value
                                        params:params
                             completionHandler:^(NSError * _Nullable error) {
                                 if (error != nil) {
                                     LogNSError("TestCluster EpochS write Error", error);
                                 }
                                 SetCommandExitStatus(error);
                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterEpochS : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterEpochS()
        : SubscribeAttribute("epoch-s")
    {
    }

    ~SubscribeAttributeTestClusterEpochS() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEpochSWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.EpochS response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorId
 */
class ReadTestClusterVendorId : public ReadAttribute {
public:
    ReadTestClusterVendorId()
        : ReadAttribute("vendor-id")
    {
    }

    ~ReadTestClusterVendorId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeVendorIdWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.VendorId response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster VendorId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterVendorId : public WriteAttribute {
public:
    WriteTestClusterVendorId()
        : WriteAttribute("vendor-id")
    {
        AddArgument("attr-name", "vendor-id");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterVendorId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeVendorIdWithValue:value
                                          params:params
                               completionHandler:^(NSError * _Nullable error) {
                                   if (error != nil) {
                                       LogNSError("TestCluster VendorId write Error", error);
                                   }
                                   SetCommandExitStatus(error);
                               }];
        return CHIP_NO_ERROR;
    }

private:
    chip::VendorId mValue;
};

class SubscribeAttributeTestClusterVendorId : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterVendorId()
        : SubscribeAttribute("vendor-id")
    {
    }

    ~SubscribeAttributeTestClusterVendorId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeVendorIdWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.VendorId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListNullablesAndOptionalsStruct
 */
class ReadTestClusterListNullablesAndOptionalsStruct : public ReadAttribute {
public:
    ReadTestClusterListNullablesAndOptionalsStruct()
        : ReadAttribute("list-nullables-and-optionals-struct")
    {
    }

    ~ReadTestClusterListNullablesAndOptionalsStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000023) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeListNullablesAndOptionalsStructWithCompletionHandler:^(
            NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ListNullablesAndOptionalsStruct response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ListNullablesAndOptionalsStruct read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListNullablesAndOptionalsStruct : public WriteAttribute {
public:
    WriteTestClusterListNullablesAndOptionalsStruct()
        : WriteAttribute("list-nullables-and-optionals-struct")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-nullables-and-optionals-struct");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListNullablesAndOptionalsStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRTestClusterClusterNullablesAndOptionalsStruct * newElement_0;
                newElement_0 = [MTRTestClusterClusterNullablesAndOptionalsStruct new];
                if (entry_0.nullableInt.IsNull()) {
                    newElement_0.nullableInt = nil;
                } else {
                    newElement_0.nullableInt = [NSNumber numberWithUnsignedShort:entry_0.nullableInt.Value()];
                }
                if (entry_0.optionalInt.HasValue()) {
                    newElement_0.optionalInt = [NSNumber numberWithUnsignedShort:entry_0.optionalInt.Value()];
                } else {
                    newElement_0.optionalInt = nil;
                }
                if (entry_0.nullableOptionalInt.HasValue()) {
                    if (entry_0.nullableOptionalInt.Value().IsNull()) {
                        newElement_0.nullableOptionalInt = nil;
                    } else {
                        newElement_0.nullableOptionalInt =
                            [NSNumber numberWithUnsignedShort:entry_0.nullableOptionalInt.Value().Value()];
                    }
                } else {
                    newElement_0.nullableOptionalInt = nil;
                }
                if (entry_0.nullableString.IsNull()) {
                    newElement_0.nullableString = nil;
                } else {
                    newElement_0.nullableString = [[NSString alloc] initWithBytes:entry_0.nullableString.Value().data()
                                                                           length:entry_0.nullableString.Value().size()
                                                                         encoding:NSUTF8StringEncoding];
                }
                if (entry_0.optionalString.HasValue()) {
                    newElement_0.optionalString = [[NSString alloc] initWithBytes:entry_0.optionalString.Value().data()
                                                                           length:entry_0.optionalString.Value().size()
                                                                         encoding:NSUTF8StringEncoding];
                } else {
                    newElement_0.optionalString = nil;
                }
                if (entry_0.nullableOptionalString.HasValue()) {
                    if (entry_0.nullableOptionalString.Value().IsNull()) {
                        newElement_0.nullableOptionalString = nil;
                    } else {
                        newElement_0.nullableOptionalString =
                            [[NSString alloc] initWithBytes:entry_0.nullableOptionalString.Value().Value().data()
                                                     length:entry_0.nullableOptionalString.Value().Value().size()
                                                   encoding:NSUTF8StringEncoding];
                    }
                } else {
                    newElement_0.nullableOptionalString = nil;
                }
                if (entry_0.nullableStruct.IsNull()) {
                    newElement_0.nullableStruct = nil;
                } else {
                    newElement_0.nullableStruct = [MTRTestClusterClusterSimpleStruct new];
                    newElement_0.nullableStruct.a = [NSNumber numberWithUnsignedChar:entry_0.nullableStruct.Value().a];
                    newElement_0.nullableStruct.b = [NSNumber numberWithBool:entry_0.nullableStruct.Value().b];
                    newElement_0.nullableStruct.c =
                        [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.nullableStruct.Value().c)];
                    newElement_0.nullableStruct.d = [NSData dataWithBytes:entry_0.nullableStruct.Value().d.data()
                                                                   length:entry_0.nullableStruct.Value().d.size()];
                    newElement_0.nullableStruct.e = [[NSString alloc] initWithBytes:entry_0.nullableStruct.Value().e.data()
                                                                             length:entry_0.nullableStruct.Value().e.size()
                                                                           encoding:NSUTF8StringEncoding];
                    newElement_0.nullableStruct.f = [NSNumber numberWithUnsignedChar:entry_0.nullableStruct.Value().f.Raw()];
                    newElement_0.nullableStruct.g = [NSNumber numberWithFloat:entry_0.nullableStruct.Value().g];
                    newElement_0.nullableStruct.h = [NSNumber numberWithDouble:entry_0.nullableStruct.Value().h];
                }
                if (entry_0.optionalStruct.HasValue()) {
                    newElement_0.optionalStruct = [MTRTestClusterClusterSimpleStruct new];
                    newElement_0.optionalStruct.a = [NSNumber numberWithUnsignedChar:entry_0.optionalStruct.Value().a];
                    newElement_0.optionalStruct.b = [NSNumber numberWithBool:entry_0.optionalStruct.Value().b];
                    newElement_0.optionalStruct.c =
                        [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.optionalStruct.Value().c)];
                    newElement_0.optionalStruct.d = [NSData dataWithBytes:entry_0.optionalStruct.Value().d.data()
                                                                   length:entry_0.optionalStruct.Value().d.size()];
                    newElement_0.optionalStruct.e = [[NSString alloc] initWithBytes:entry_0.optionalStruct.Value().e.data()
                                                                             length:entry_0.optionalStruct.Value().e.size()
                                                                           encoding:NSUTF8StringEncoding];
                    newElement_0.optionalStruct.f = [NSNumber numberWithUnsignedChar:entry_0.optionalStruct.Value().f.Raw()];
                    newElement_0.optionalStruct.g = [NSNumber numberWithFloat:entry_0.optionalStruct.Value().g];
                    newElement_0.optionalStruct.h = [NSNumber numberWithDouble:entry_0.optionalStruct.Value().h];
                } else {
                    newElement_0.optionalStruct = nil;
                }
                if (entry_0.nullableOptionalStruct.HasValue()) {
                    if (entry_0.nullableOptionalStruct.Value().IsNull()) {
                        newElement_0.nullableOptionalStruct = nil;
                    } else {
                        newElement_0.nullableOptionalStruct = [MTRTestClusterClusterSimpleStruct new];
                        newElement_0.nullableOptionalStruct.a =
                            [NSNumber numberWithUnsignedChar:entry_0.nullableOptionalStruct.Value().Value().a];
                        newElement_0.nullableOptionalStruct.b =
                            [NSNumber numberWithBool:entry_0.nullableOptionalStruct.Value().Value().b];
                        newElement_0.nullableOptionalStruct.c =
                            [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.nullableOptionalStruct.Value().Value().c)];
                        newElement_0.nullableOptionalStruct.d =
                            [NSData dataWithBytes:entry_0.nullableOptionalStruct.Value().Value().d.data()
                                           length:entry_0.nullableOptionalStruct.Value().Value().d.size()];
                        newElement_0.nullableOptionalStruct.e =
                            [[NSString alloc] initWithBytes:entry_0.nullableOptionalStruct.Value().Value().e.data()
                                                     length:entry_0.nullableOptionalStruct.Value().Value().e.size()
                                                   encoding:NSUTF8StringEncoding];
                        newElement_0.nullableOptionalStruct.f =
                            [NSNumber numberWithUnsignedChar:entry_0.nullableOptionalStruct.Value().Value().f.Raw()];
                        newElement_0.nullableOptionalStruct.g =
                            [NSNumber numberWithFloat:entry_0.nullableOptionalStruct.Value().Value().g];
                        newElement_0.nullableOptionalStruct.h =
                            [NSNumber numberWithDouble:entry_0.nullableOptionalStruct.Value().Value().h];
                    }
                } else {
                    newElement_0.nullableOptionalStruct = nil;
                }
                if (entry_0.nullableList.IsNull()) {
                    newElement_0.nullableList = nil;
                } else {
                    { // Scope for our temporary variables
                        auto * array_3 = [NSMutableArray new];
                        for (auto & entry_3 : entry_0.nullableList.Value()) {
                            NSNumber * newElement_3;
                            newElement_3 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_3)];
                            [array_3 addObject:newElement_3];
                        }
                        newElement_0.nullableList = array_3;
                    }
                }
                if (entry_0.optionalList.HasValue()) {
                    { // Scope for our temporary variables
                        auto * array_3 = [NSMutableArray new];
                        for (auto & entry_3 : entry_0.optionalList.Value()) {
                            NSNumber * newElement_3;
                            newElement_3 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_3)];
                            [array_3 addObject:newElement_3];
                        }
                        newElement_0.optionalList = array_3;
                    }
                } else {
                    newElement_0.optionalList = nil;
                }
                if (entry_0.nullableOptionalList.HasValue()) {
                    if (entry_0.nullableOptionalList.Value().IsNull()) {
                        newElement_0.nullableOptionalList = nil;
                    } else {
                        { // Scope for our temporary variables
                            auto * array_4 = [NSMutableArray new];
                            for (auto & entry_4 : entry_0.nullableOptionalList.Value().Value()) {
                                NSNumber * newElement_4;
                                newElement_4 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_4)];
                                [array_4 addObject:newElement_4];
                            }
                            newElement_0.nullableOptionalList = array_4;
                        }
                    }
                } else {
                    newElement_0.nullableOptionalList = nil;
                }
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListNullablesAndOptionalsStructWithValue:value
                                                                 params:params
                                                      completionHandler:^(NSError * _Nullable error) {
                                                          if (error != nil) {
                                                              LogNSError(
                                                                  "TestCluster ListNullablesAndOptionalsStruct write Error", error);
                                                          }
                                                          SetCommandExitStatus(error);
                                                      }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::NullablesAndOptionalsStruct::Type> mValue;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::NullablesAndOptionalsStruct::Type>>
        mComplex;
};

class SubscribeAttributeTestClusterListNullablesAndOptionalsStruct : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListNullablesAndOptionalsStruct()
        : SubscribeAttribute("list-nullables-and-optionals-struct")
    {
    }

    ~SubscribeAttributeTestClusterListNullablesAndOptionalsStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeListNullablesAndOptionalsStructWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListNullablesAndOptionalsStruct response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnumAttr
 */
class ReadTestClusterEnumAttr : public ReadAttribute {
public:
    ReadTestClusterEnumAttr()
        : ReadAttribute("enum-attr")
    {
    }

    ~ReadTestClusterEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeEnumAttrWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.EnumAttr response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster EnumAttr read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterEnumAttr : public WriteAttribute {
public:
    WriteTestClusterEnumAttr()
        : WriteAttribute("enum-attr")
    {
        AddArgument("attr-name", "enum-attr");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeEnumAttrWithValue:value
                                          params:params
                               completionHandler:^(NSError * _Nullable error) {
                                   if (error != nil) {
                                       LogNSError("TestCluster EnumAttr write Error", error);
                                   }
                                   SetCommandExitStatus(error);
                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterEnumAttr : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterEnumAttr()
        : SubscribeAttribute("enum-attr")
    {
    }

    ~SubscribeAttributeTestClusterEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeEnumAttrWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.EnumAttr response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StructAttr
 */
class ReadTestClusterStructAttr : public ReadAttribute {
public:
    ReadTestClusterStructAttr()
        : ReadAttribute("struct-attr")
    {
    }

    ~ReadTestClusterStructAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeStructAttrWithCompletionHandler:^(
            MTRTestClusterClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.StructAttr response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster StructAttr read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterStructAttr : public WriteAttribute {
public:
    WriteTestClusterStructAttr()
        : WriteAttribute("struct-attr")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "struct-attr");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterStructAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        MTRTestClusterClusterSimpleStruct * _Nonnull value;
        value = [MTRTestClusterClusterSimpleStruct new];
        value.a = [NSNumber numberWithUnsignedChar:mValue.a];
        value.b = [NSNumber numberWithBool:mValue.b];
        value.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mValue.c)];
        value.d = [NSData dataWithBytes:mValue.d.data() length:mValue.d.size()];
        value.e = [[NSString alloc] initWithBytes:mValue.e.data() length:mValue.e.size() encoding:NSUTF8StringEncoding];
        value.f = [NSNumber numberWithUnsignedChar:mValue.f.Raw()];
        value.g = [NSNumber numberWithFloat:mValue.g];
        value.h = [NSNumber numberWithDouble:mValue.h];

        [cluster writeAttributeStructAttrWithValue:value
                                            params:params
                                 completionHandler:^(NSError * _Nullable error) {
                                     if (error != nil) {
                                         LogNSError("TestCluster StructAttr write Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type mValue;
    TypedComplexArgument<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type> mComplex;
};

class SubscribeAttributeTestClusterStructAttr : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterStructAttr()
        : SubscribeAttribute("struct-attr")
    {
    }

    ~SubscribeAttributeTestClusterStructAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeStructAttrWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRTestClusterClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.StructAttr response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt8u
 */
class ReadTestClusterRangeRestrictedInt8u : public ReadAttribute {
public:
    ReadTestClusterRangeRestrictedInt8u()
        : ReadAttribute("range-restricted-int8u")
    {
    }

    ~ReadTestClusterRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt8uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.RangeRestrictedInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster RangeRestrictedInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterRangeRestrictedInt8u : public WriteAttribute {
public:
    WriteTestClusterRangeRestrictedInt8u()
        : WriteAttribute("range-restricted-int8u")
    {
        AddArgument("attr-name", "range-restricted-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeRangeRestrictedInt8uWithValue:value
                                                      params:params
                                           completionHandler:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("TestCluster RangeRestrictedInt8u write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterRangeRestrictedInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterRangeRestrictedInt8u()
        : SubscribeAttribute("range-restricted-int8u")
    {
    }

    ~SubscribeAttributeTestClusterRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRangeRestrictedInt8uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.RangeRestrictedInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt8s
 */
class ReadTestClusterRangeRestrictedInt8s : public ReadAttribute {
public:
    ReadTestClusterRangeRestrictedInt8s()
        : ReadAttribute("range-restricted-int8s")
    {
    }

    ~ReadTestClusterRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000027) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt8sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.RangeRestrictedInt8s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster RangeRestrictedInt8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterRangeRestrictedInt8s : public WriteAttribute {
public:
    WriteTestClusterRangeRestrictedInt8s()
        : WriteAttribute("range-restricted-int8s")
    {
        AddArgument("attr-name", "range-restricted-int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeRangeRestrictedInt8sWithValue:value
                                                      params:params
                                           completionHandler:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("TestCluster RangeRestrictedInt8s write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeTestClusterRangeRestrictedInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterRangeRestrictedInt8s()
        : SubscribeAttribute("range-restricted-int8s")
    {
    }

    ~SubscribeAttributeTestClusterRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRangeRestrictedInt8sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.RangeRestrictedInt8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt16u
 */
class ReadTestClusterRangeRestrictedInt16u : public ReadAttribute {
public:
    ReadTestClusterRangeRestrictedInt16u()
        : ReadAttribute("range-restricted-int16u")
    {
    }

    ~ReadTestClusterRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000028) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt16uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.RangeRestrictedInt16u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster RangeRestrictedInt16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterRangeRestrictedInt16u : public WriteAttribute {
public:
    WriteTestClusterRangeRestrictedInt16u()
        : WriteAttribute("range-restricted-int16u")
    {
        AddArgument("attr-name", "range-restricted-int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeRangeRestrictedInt16uWithValue:value
                                                       params:params
                                            completionHandler:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster RangeRestrictedInt16u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterRangeRestrictedInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterRangeRestrictedInt16u()
        : SubscribeAttribute("range-restricted-int16u")
    {
    }

    ~SubscribeAttributeTestClusterRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRangeRestrictedInt16uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.RangeRestrictedInt16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt16s
 */
class ReadTestClusterRangeRestrictedInt16s : public ReadAttribute {
public:
    ReadTestClusterRangeRestrictedInt16s()
        : ReadAttribute("range-restricted-int16s")
    {
    }

    ~ReadTestClusterRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt16sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.RangeRestrictedInt16s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster RangeRestrictedInt16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterRangeRestrictedInt16s : public WriteAttribute {
public:
    WriteTestClusterRangeRestrictedInt16s()
        : WriteAttribute("range-restricted-int16s")
    {
        AddArgument("attr-name", "range-restricted-int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeRangeRestrictedInt16sWithValue:value
                                                       params:params
                                            completionHandler:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster RangeRestrictedInt16s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeTestClusterRangeRestrictedInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterRangeRestrictedInt16s()
        : SubscribeAttribute("range-restricted-int16s")
    {
    }

    ~SubscribeAttributeTestClusterRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeRangeRestrictedInt16sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.RangeRestrictedInt16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListLongOctetString
 */
class ReadTestClusterListLongOctetString : public ReadAttribute {
public:
    ReadTestClusterListLongOctetString()
        : ReadAttribute("list-long-octet-string")
    {
    }

    ~ReadTestClusterListLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000002A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeListLongOctetStringWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ListLongOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ListLongOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListLongOctetString : public WriteAttribute {
public:
    WriteTestClusterListLongOctetString()
        : WriteAttribute("list-long-octet-string")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-long-octet-string");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                NSData * newElement_0;
                newElement_0 = [NSData dataWithBytes:entry_0.data() length:entry_0.size()];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListLongOctetStringWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("TestCluster ListLongOctetString write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::ByteSpan> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::ByteSpan>> mComplex;
};

class SubscribeAttributeTestClusterListLongOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListLongOctetString()
        : SubscribeAttribute("list-long-octet-string")
    {
    }

    ~SubscribeAttributeTestClusterListLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeListLongOctetStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListLongOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListFabricScoped
 */
class ReadTestClusterListFabricScoped : public ReadAttribute {
public:
    ReadTestClusterListFabricScoped()
        : ReadAttribute("list-fabric-scoped")
    {
    }

    ~ReadTestClusterListFabricScoped() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000002B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster readAttributeListFabricScopedWithParams:params
                                       completionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                           NSLog(@"TestCluster.ListFabricScoped response %@", [value description]);
                                           if (error != nil) {
                                               LogNSError("TestCluster ListFabricScoped read Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListFabricScoped : public WriteAttribute {
public:
    WriteTestClusterListFabricScoped()
        : WriteAttribute("list-fabric-scoped")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-fabric-scoped");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListFabricScoped() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000002B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSArray * _Nonnull value;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mValue) {
                MTRTestClusterClusterTestFabricScoped * newElement_0;
                newElement_0 = [MTRTestClusterClusterTestFabricScoped new];
                newElement_0.fabricSensitiveInt8u = [NSNumber numberWithUnsignedChar:entry_0.fabricSensitiveInt8u];
                if (entry_0.optionalFabricSensitiveInt8u.HasValue()) {
                    newElement_0.optionalFabricSensitiveInt8u =
                        [NSNumber numberWithUnsignedChar:entry_0.optionalFabricSensitiveInt8u.Value()];
                } else {
                    newElement_0.optionalFabricSensitiveInt8u = nil;
                }
                if (entry_0.nullableFabricSensitiveInt8u.IsNull()) {
                    newElement_0.nullableFabricSensitiveInt8u = nil;
                } else {
                    newElement_0.nullableFabricSensitiveInt8u =
                        [NSNumber numberWithUnsignedChar:entry_0.nullableFabricSensitiveInt8u.Value()];
                }
                if (entry_0.nullableOptionalFabricSensitiveInt8u.HasValue()) {
                    if (entry_0.nullableOptionalFabricSensitiveInt8u.Value().IsNull()) {
                        newElement_0.nullableOptionalFabricSensitiveInt8u = nil;
                    } else {
                        newElement_0.nullableOptionalFabricSensitiveInt8u =
                            [NSNumber numberWithUnsignedChar:entry_0.nullableOptionalFabricSensitiveInt8u.Value().Value()];
                    }
                } else {
                    newElement_0.nullableOptionalFabricSensitiveInt8u = nil;
                }
                newElement_0.fabricSensitiveCharString = [[NSString alloc] initWithBytes:entry_0.fabricSensitiveCharString.data()
                                                                                  length:entry_0.fabricSensitiveCharString.size()
                                                                                encoding:NSUTF8StringEncoding];
                newElement_0.fabricSensitiveStruct = [MTRTestClusterClusterSimpleStruct new];
                newElement_0.fabricSensitiveStruct.a = [NSNumber numberWithUnsignedChar:entry_0.fabricSensitiveStruct.a];
                newElement_0.fabricSensitiveStruct.b = [NSNumber numberWithBool:entry_0.fabricSensitiveStruct.b];
                newElement_0.fabricSensitiveStruct.c =
                    [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.fabricSensitiveStruct.c)];
                newElement_0.fabricSensitiveStruct.d = [NSData dataWithBytes:entry_0.fabricSensitiveStruct.d.data()
                                                                      length:entry_0.fabricSensitiveStruct.d.size()];
                newElement_0.fabricSensitiveStruct.e = [[NSString alloc] initWithBytes:entry_0.fabricSensitiveStruct.e.data()
                                                                                length:entry_0.fabricSensitiveStruct.e.size()
                                                                              encoding:NSUTF8StringEncoding];
                newElement_0.fabricSensitiveStruct.f = [NSNumber numberWithUnsignedChar:entry_0.fabricSensitiveStruct.f.Raw()];
                newElement_0.fabricSensitiveStruct.g = [NSNumber numberWithFloat:entry_0.fabricSensitiveStruct.g];
                newElement_0.fabricSensitiveStruct.h = [NSNumber numberWithDouble:entry_0.fabricSensitiveStruct.h];
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.fabricSensitiveInt8uList) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedChar:entry_2];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.fabricSensitiveInt8uList = array_2;
                }
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListFabricScopedWithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("TestCluster ListFabricScoped write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::TestFabricScoped::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::TestFabricScoped::Type>>
        mComplex;
};

class SubscribeAttributeTestClusterListFabricScoped : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListFabricScoped()
        : SubscribeAttribute("list-fabric-scoped")
    {
    }

    ~SubscribeAttributeTestClusterListFabricScoped() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000002B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeListFabricScopedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListFabricScoped response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TimedWriteBoolean
 */
class ReadTestClusterTimedWriteBoolean : public ReadAttribute {
public:
    ReadTestClusterTimedWriteBoolean()
        : ReadAttribute("timed-write-boolean")
    {
    }

    ~ReadTestClusterTimedWriteBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeTimedWriteBooleanWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.TimedWriteBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster TimedWriteBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterTimedWriteBoolean : public WriteAttribute {
public:
    WriteTestClusterTimedWriteBoolean()
        : WriteAttribute("timed-write-boolean")
    {
        AddArgument("attr-name", "timed-write-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterTimedWriteBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeTimedWriteBooleanWithValue:value
                                                   params:params
                                        completionHandler:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("TestCluster TimedWriteBoolean write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterTimedWriteBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterTimedWriteBoolean()
        : SubscribeAttribute("timed-write-boolean")
    {
    }

    ~SubscribeAttributeTestClusterTimedWriteBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeTimedWriteBooleanWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.TimedWriteBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneralErrorBoolean
 */
class ReadTestClusterGeneralErrorBoolean : public ReadAttribute {
public:
    ReadTestClusterGeneralErrorBoolean()
        : ReadAttribute("general-error-boolean")
    {
    }

    ~ReadTestClusterGeneralErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneralErrorBooleanWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.GeneralErrorBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster GeneralErrorBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterGeneralErrorBoolean : public WriteAttribute {
public:
    WriteTestClusterGeneralErrorBoolean()
        : WriteAttribute("general-error-boolean")
    {
        AddArgument("attr-name", "general-error-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterGeneralErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeGeneralErrorBooleanWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("TestCluster GeneralErrorBoolean write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterGeneralErrorBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterGeneralErrorBoolean()
        : SubscribeAttribute("general-error-boolean")
    {
    }

    ~SubscribeAttributeTestClusterGeneralErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneralErrorBooleanWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.GeneralErrorBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterErrorBoolean
 */
class ReadTestClusterClusterErrorBoolean : public ReadAttribute {
public:
    ReadTestClusterClusterErrorBoolean()
        : ReadAttribute("cluster-error-boolean")
    {
    }

    ~ReadTestClusterClusterErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterErrorBooleanWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ClusterErrorBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ClusterErrorBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterClusterErrorBoolean : public WriteAttribute {
public:
    WriteTestClusterClusterErrorBoolean()
        : WriteAttribute("cluster-error-boolean")
    {
        AddArgument("attr-name", "cluster-error-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterClusterErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeClusterErrorBooleanWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("TestCluster ClusterErrorBoolean write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterClusterErrorBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterClusterErrorBoolean()
        : SubscribeAttribute("cluster-error-boolean")
    {
    }

    ~SubscribeAttributeTestClusterClusterErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterErrorBooleanWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ClusterErrorBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Unsupported
 */
class ReadTestClusterUnsupported : public ReadAttribute {
public:
    ReadTestClusterUnsupported()
        : ReadAttribute("unsupported")
    {
    }

    ~ReadTestClusterUnsupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x000000FF) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeUnsupportedWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Unsupported response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Unsupported read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterUnsupported : public WriteAttribute {
public:
    WriteTestClusterUnsupported()
        : WriteAttribute("unsupported")
    {
        AddArgument("attr-name", "unsupported");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterUnsupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x000000FF) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeUnsupportedWithValue:value
                                             params:params
                                  completionHandler:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("TestCluster Unsupported write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterUnsupported : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterUnsupported()
        : SubscribeAttribute("unsupported")
    {
    }

    ~SubscribeAttributeTestClusterUnsupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x000000FF) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeUnsupportedWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Unsupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBoolean
 */
class ReadTestClusterNullableBoolean : public ReadAttribute {
public:
    ReadTestClusterNullableBoolean()
        : ReadAttribute("nullable-boolean")
    {
    }

    ~ReadTestClusterNullableBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableBooleanWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableBoolean : public WriteAttribute {
public:
    WriteTestClusterNullableBoolean()
        : WriteAttribute("nullable-boolean")
    {
        AddArgument("attr-name", "nullable-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeNullableBooleanWithValue:value
                                                 params:params
                                      completionHandler:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("TestCluster NullableBoolean write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterNullableBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableBoolean()
        : SubscribeAttribute("nullable-boolean")
    {
    }

    ~SubscribeAttributeTestClusterNullableBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableBooleanWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap8
 */
class ReadTestClusterNullableBitmap8 : public ReadAttribute {
public:
    ReadTestClusterNullableBitmap8()
        : ReadAttribute("nullable-bitmap8")
    {
    }

    ~ReadTestClusterNullableBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableBitmap8WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableBitmap8 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableBitmap8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableBitmap8 : public WriteAttribute {
public:
    WriteTestClusterNullableBitmap8()
        : WriteAttribute("nullable-bitmap8")
    {
        AddArgument("attr-name", "nullable-bitmap8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableBitmap8WithValue:value
                                                 params:params
                                      completionHandler:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("TestCluster NullableBitmap8 write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterNullableBitmap8 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableBitmap8()
        : SubscribeAttribute("nullable-bitmap8")
    {
    }

    ~SubscribeAttributeTestClusterNullableBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableBitmap8WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableBitmap8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap16
 */
class ReadTestClusterNullableBitmap16 : public ReadAttribute {
public:
    ReadTestClusterNullableBitmap16()
        : ReadAttribute("nullable-bitmap16")
    {
    }

    ~ReadTestClusterNullableBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableBitmap16WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableBitmap16 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableBitmap16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableBitmap16 : public WriteAttribute {
public:
    WriteTestClusterNullableBitmap16()
        : WriteAttribute("nullable-bitmap16")
    {
        AddArgument("attr-name", "nullable-bitmap16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeNullableBitmap16WithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("TestCluster NullableBitmap16 write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterNullableBitmap16 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableBitmap16()
        : SubscribeAttribute("nullable-bitmap16")
    {
    }

    ~SubscribeAttributeTestClusterNullableBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableBitmap16WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableBitmap16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap32
 */
class ReadTestClusterNullableBitmap32 : public ReadAttribute {
public:
    ReadTestClusterNullableBitmap32()
        : ReadAttribute("nullable-bitmap32")
    {
    }

    ~ReadTestClusterNullableBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableBitmap32WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableBitmap32 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableBitmap32 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableBitmap32 : public WriteAttribute {
public:
    WriteTestClusterNullableBitmap32()
        : WriteAttribute("nullable-bitmap32")
    {
        AddArgument("attr-name", "nullable-bitmap32");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeNullableBitmap32WithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("TestCluster NullableBitmap32 write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterNullableBitmap32 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableBitmap32()
        : SubscribeAttribute("nullable-bitmap32")
    {
    }

    ~SubscribeAttributeTestClusterNullableBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableBitmap32WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableBitmap32 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap64
 */
class ReadTestClusterNullableBitmap64 : public ReadAttribute {
public:
    ReadTestClusterNullableBitmap64()
        : ReadAttribute("nullable-bitmap64")
    {
    }

    ~ReadTestClusterNullableBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableBitmap64WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableBitmap64 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableBitmap64 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableBitmap64 : public WriteAttribute {
public:
    WriteTestClusterNullableBitmap64()
        : WriteAttribute("nullable-bitmap64")
    {
        AddArgument("attr-name", "nullable-bitmap64");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableBitmap64WithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("TestCluster NullableBitmap64 write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterNullableBitmap64 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableBitmap64()
        : SubscribeAttribute("nullable-bitmap64")
    {
    }

    ~SubscribeAttributeTestClusterNullableBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableBitmap64WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableBitmap64 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt8u
 */
class ReadTestClusterNullableInt8u : public ReadAttribute {
public:
    ReadTestClusterNullableInt8u()
        : ReadAttribute("nullable-int8u")
    {
    }

    ~ReadTestClusterNullableInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt8uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt8u : public WriteAttribute {
public:
    WriteTestClusterNullableInt8u()
        : WriteAttribute("nullable-int8u")
    {
        AddArgument("attr-name", "nullable-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableInt8uWithValue:value
                                               params:params
                                    completionHandler:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster NullableInt8u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterNullableInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt8u()
        : SubscribeAttribute("nullable-int8u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt8uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt16u
 */
class ReadTestClusterNullableInt16u : public ReadAttribute {
public:
    ReadTestClusterNullableInt16u()
        : ReadAttribute("nullable-int16u")
    {
    }

    ~ReadTestClusterNullableInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt16uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt16u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt16u : public WriteAttribute {
public:
    WriteTestClusterNullableInt16u()
        : WriteAttribute("nullable-int16u")
    {
        AddArgument("attr-name", "nullable-int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeNullableInt16uWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt16u write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterNullableInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt16u()
        : SubscribeAttribute("nullable-int16u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt16uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt24u
 */
class ReadTestClusterNullableInt24u : public ReadAttribute {
public:
    ReadTestClusterNullableInt24u()
        : ReadAttribute("nullable-int24u")
    {
    }

    ~ReadTestClusterNullableInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt24uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt24u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt24u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt24u : public WriteAttribute {
public:
    WriteTestClusterNullableInt24u()
        : WriteAttribute("nullable-int24u")
    {
        AddArgument("attr-name", "nullable-int24u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeNullableInt24uWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt24u write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterNullableInt24u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt24u()
        : SubscribeAttribute("nullable-int24u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt24uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt24u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt32u
 */
class ReadTestClusterNullableInt32u : public ReadAttribute {
public:
    ReadTestClusterNullableInt32u()
        : ReadAttribute("nullable-int32u")
    {
    }

    ~ReadTestClusterNullableInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt32uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt32u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt32u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt32u : public WriteAttribute {
public:
    WriteTestClusterNullableInt32u()
        : WriteAttribute("nullable-int32u")
    {
        AddArgument("attr-name", "nullable-int32u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeNullableInt32uWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt32u write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterNullableInt32u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt32u()
        : SubscribeAttribute("nullable-int32u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt32uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt32u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt40u
 */
class ReadTestClusterNullableInt40u : public ReadAttribute {
public:
    ReadTestClusterNullableInt40u()
        : ReadAttribute("nullable-int40u")
    {
    }

    ~ReadTestClusterNullableInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt40uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt40u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt40u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt40u : public WriteAttribute {
public:
    WriteTestClusterNullableInt40u()
        : WriteAttribute("nullable-int40u")
    {
        AddArgument("attr-name", "nullable-int40u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt40uWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt40u write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt40u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt40u()
        : SubscribeAttribute("nullable-int40u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt40uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt40u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt48u
 */
class ReadTestClusterNullableInt48u : public ReadAttribute {
public:
    ReadTestClusterNullableInt48u()
        : ReadAttribute("nullable-int48u")
    {
    }

    ~ReadTestClusterNullableInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt48uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt48u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt48u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt48u : public WriteAttribute {
public:
    WriteTestClusterNullableInt48u()
        : WriteAttribute("nullable-int48u")
    {
        AddArgument("attr-name", "nullable-int48u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt48uWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt48u write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt48u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt48u()
        : SubscribeAttribute("nullable-int48u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt48uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt48u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt56u
 */
class ReadTestClusterNullableInt56u : public ReadAttribute {
public:
    ReadTestClusterNullableInt56u()
        : ReadAttribute("nullable-int56u")
    {
    }

    ~ReadTestClusterNullableInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt56uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt56u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt56u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt56u : public WriteAttribute {
public:
    WriteTestClusterNullableInt56u()
        : WriteAttribute("nullable-int56u")
    {
        AddArgument("attr-name", "nullable-int56u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt56uWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt56u write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt56u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt56u()
        : SubscribeAttribute("nullable-int56u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt56uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt56u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt64u
 */
class ReadTestClusterNullableInt64u : public ReadAttribute {
public:
    ReadTestClusterNullableInt64u()
        : ReadAttribute("nullable-int64u")
    {
    }

    ~ReadTestClusterNullableInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt64uWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt64u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt64u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt64u : public WriteAttribute {
public:
    WriteTestClusterNullableInt64u()
        : WriteAttribute("nullable-int64u")
    {
        AddArgument("attr-name", "nullable-int64u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt64uWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt64u write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt64u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt64u()
        : SubscribeAttribute("nullable-int64u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt64uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt64u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt8s
 */
class ReadTestClusterNullableInt8s : public ReadAttribute {
public:
    ReadTestClusterNullableInt8s()
        : ReadAttribute("nullable-int8s")
    {
    }

    ~ReadTestClusterNullableInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt8sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt8s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt8s : public WriteAttribute {
public:
    WriteTestClusterNullableInt8s()
        : WriteAttribute("nullable-int8s")
    {
        AddArgument("attr-name", "nullable-int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeNullableInt8sWithValue:value
                                               params:params
                                    completionHandler:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster NullableInt8s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeTestClusterNullableInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt8s()
        : SubscribeAttribute("nullable-int8s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt8sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt16s
 */
class ReadTestClusterNullableInt16s : public ReadAttribute {
public:
    ReadTestClusterNullableInt16s()
        : ReadAttribute("nullable-int16s")
    {
    }

    ~ReadTestClusterNullableInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt16sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt16s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt16s : public WriteAttribute {
public:
    WriteTestClusterNullableInt16s()
        : WriteAttribute("nullable-int16s")
    {
        AddArgument("attr-name", "nullable-int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeNullableInt16sWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt16s write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeTestClusterNullableInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt16s()
        : SubscribeAttribute("nullable-int16s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt16sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt24s
 */
class ReadTestClusterNullableInt24s : public ReadAttribute {
public:
    ReadTestClusterNullableInt24s()
        : ReadAttribute("nullable-int24s")
    {
    }

    ~ReadTestClusterNullableInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt24sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt24s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt24s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt24s : public WriteAttribute {
public:
    WriteTestClusterNullableInt24s()
        : WriteAttribute("nullable-int24s")
    {
        AddArgument("attr-name", "nullable-int24s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeNullableInt24sWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt24s write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeTestClusterNullableInt24s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt24s()
        : SubscribeAttribute("nullable-int24s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt24sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt24s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt32s
 */
class ReadTestClusterNullableInt32s : public ReadAttribute {
public:
    ReadTestClusterNullableInt32s()
        : ReadAttribute("nullable-int32s")
    {
    }

    ~ReadTestClusterNullableInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt32sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt32s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt32s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt32s : public WriteAttribute {
public:
    WriteTestClusterNullableInt32s()
        : WriteAttribute("nullable-int32s")
    {
        AddArgument("attr-name", "nullable-int32s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeNullableInt32sWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt32s write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeTestClusterNullableInt32s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt32s()
        : SubscribeAttribute("nullable-int32s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt32sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt32s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt40s
 */
class ReadTestClusterNullableInt40s : public ReadAttribute {
public:
    ReadTestClusterNullableInt40s()
        : ReadAttribute("nullable-int40s")
    {
    }

    ~ReadTestClusterNullableInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt40sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt40s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt40s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt40s : public WriteAttribute {
public:
    WriteTestClusterNullableInt40s()
        : WriteAttribute("nullable-int40s")
    {
        AddArgument("attr-name", "nullable-int40s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt40sWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt40s write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt40s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt40s()
        : SubscribeAttribute("nullable-int40s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt40sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt40s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt48s
 */
class ReadTestClusterNullableInt48s : public ReadAttribute {
public:
    ReadTestClusterNullableInt48s()
        : ReadAttribute("nullable-int48s")
    {
    }

    ~ReadTestClusterNullableInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt48sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt48s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt48s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt48s : public WriteAttribute {
public:
    WriteTestClusterNullableInt48s()
        : WriteAttribute("nullable-int48s")
    {
        AddArgument("attr-name", "nullable-int48s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt48sWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt48s write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt48s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt48s()
        : SubscribeAttribute("nullable-int48s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt48sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt48s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt56s
 */
class ReadTestClusterNullableInt56s : public ReadAttribute {
public:
    ReadTestClusterNullableInt56s()
        : ReadAttribute("nullable-int56s")
    {
    }

    ~ReadTestClusterNullableInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt56sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt56s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt56s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt56s : public WriteAttribute {
public:
    WriteTestClusterNullableInt56s()
        : WriteAttribute("nullable-int56s")
    {
        AddArgument("attr-name", "nullable-int56s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt56sWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt56s write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt56s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt56s()
        : SubscribeAttribute("nullable-int56s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt56sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt56s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt64s
 */
class ReadTestClusterNullableInt64s : public ReadAttribute {
public:
    ReadTestClusterNullableInt64s()
        : ReadAttribute("nullable-int64s")
    {
    }

    ~ReadTestClusterNullableInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt64sWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt64s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt64s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt64s : public WriteAttribute {
public:
    WriteTestClusterNullableInt64s()
        : WriteAttribute("nullable-int64s")
    {
        AddArgument("attr-name", "nullable-int64s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt64sWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableInt64s write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt64s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt64s()
        : SubscribeAttribute("nullable-int64s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableInt64sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt64s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableEnum8
 */
class ReadTestClusterNullableEnum8 : public ReadAttribute {
public:
    ReadTestClusterNullableEnum8()
        : ReadAttribute("nullable-enum8")
    {
    }

    ~ReadTestClusterNullableEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableEnum8WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableEnum8 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableEnum8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableEnum8 : public WriteAttribute {
public:
    WriteTestClusterNullableEnum8()
        : WriteAttribute("nullable-enum8")
    {
        AddArgument("attr-name", "nullable-enum8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableEnum8WithValue:value
                                               params:params
                                    completionHandler:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster NullableEnum8 write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterNullableEnum8 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableEnum8()
        : SubscribeAttribute("nullable-enum8")
    {
    }

    ~SubscribeAttributeTestClusterNullableEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableEnum8WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableEnum8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableEnum16
 */
class ReadTestClusterNullableEnum16 : public ReadAttribute {
public:
    ReadTestClusterNullableEnum16()
        : ReadAttribute("nullable-enum16")
    {
    }

    ~ReadTestClusterNullableEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableEnum16WithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableEnum16 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableEnum16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableEnum16 : public WriteAttribute {
public:
    WriteTestClusterNullableEnum16()
        : WriteAttribute("nullable-enum16")
    {
        AddArgument("attr-name", "nullable-enum16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeNullableEnum16WithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableEnum16 write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterNullableEnum16 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableEnum16()
        : SubscribeAttribute("nullable-enum16")
    {
    }

    ~SubscribeAttributeTestClusterNullableEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableEnum16WithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableEnum16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableFloatSingle
 */
class ReadTestClusterNullableFloatSingle : public ReadAttribute {
public:
    ReadTestClusterNullableFloatSingle()
        : ReadAttribute("nullable-float-single")
    {
    }

    ~ReadTestClusterNullableFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableFloatSingleWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableFloatSingle response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableFloatSingle read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableFloatSingle : public WriteAttribute {
public:
    WriteTestClusterNullableFloatSingle()
        : WriteAttribute("nullable-float-single")
    {
        AddArgument("attr-name", "nullable-float-single");
        AddArgument("attr-value", -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithFloat:mValue];

        [cluster writeAttributeNullableFloatSingleWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("TestCluster NullableFloatSingle write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    float mValue;
};

class SubscribeAttributeTestClusterNullableFloatSingle : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableFloatSingle()
        : SubscribeAttribute("nullable-float-single")
    {
    }

    ~SubscribeAttributeTestClusterNullableFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableFloatSingleWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableFloatSingle response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableFloatDouble
 */
class ReadTestClusterNullableFloatDouble : public ReadAttribute {
public:
    ReadTestClusterNullableFloatDouble()
        : ReadAttribute("nullable-float-double")
    {
    }

    ~ReadTestClusterNullableFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableFloatDoubleWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableFloatDouble response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableFloatDouble read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableFloatDouble : public WriteAttribute {
public:
    WriteTestClusterNullableFloatDouble()
        : WriteAttribute("nullable-float-double")
    {
        AddArgument("attr-name", "nullable-float-double");
        AddArgument("attr-value", -std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity(), &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithDouble:mValue];

        [cluster writeAttributeNullableFloatDoubleWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("TestCluster NullableFloatDouble write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    double mValue;
};

class SubscribeAttributeTestClusterNullableFloatDouble : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableFloatDouble()
        : SubscribeAttribute("nullable-float-double")
    {
    }

    ~SubscribeAttributeTestClusterNullableFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableFloatDoubleWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableFloatDouble response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableOctetString
 */
class ReadTestClusterNullableOctetString : public ReadAttribute {
public:
    ReadTestClusterNullableOctetString()
        : ReadAttribute("nullable-octet-string")
    {
    }

    ~ReadTestClusterNullableOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableOctetStringWithCompletionHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableOctetString : public WriteAttribute {
public:
    WriteTestClusterNullableOctetString()
        : WriteAttribute("nullable-octet-string")
    {
        AddArgument("attr-name", "nullable-octet-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSData * _Nullable value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()];

        [cluster writeAttributeNullableOctetStringWithValue:value
                                                     params:params
                                          completionHandler:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("TestCluster NullableOctetString write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterNullableOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableOctetString()
        : SubscribeAttribute("nullable-octet-string")
    {
    }

    ~SubscribeAttributeTestClusterNullableOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableOctetStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableCharString
 */
class ReadTestClusterNullableCharString : public ReadAttribute {
public:
    ReadTestClusterNullableCharString()
        : ReadAttribute("nullable-char-string")
    {
    }

    ~ReadTestClusterNullableCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000401E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableCharStringWithCompletionHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableCharString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableCharString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableCharString : public WriteAttribute {
public:
    WriteTestClusterNullableCharString()
        : WriteAttribute("nullable-char-string")
    {
        AddArgument("attr-name", "nullable-char-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000401E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nullable value = [[NSString alloc] initWithBytes:mValue.data()
                                                              length:mValue.size()
                                                            encoding:NSUTF8StringEncoding];

        [cluster writeAttributeNullableCharStringWithValue:value
                                                    params:params
                                         completionHandler:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("TestCluster NullableCharString write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterNullableCharString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableCharString()
        : SubscribeAttribute("nullable-char-string")
    {
    }

    ~SubscribeAttributeTestClusterNullableCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000401E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableCharStringWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableCharString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableEnumAttr
 */
class ReadTestClusterNullableEnumAttr : public ReadAttribute {
public:
    ReadTestClusterNullableEnumAttr()
        : ReadAttribute("nullable-enum-attr")
    {
    }

    ~ReadTestClusterNullableEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableEnumAttrWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableEnumAttr response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableEnumAttr read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableEnumAttr : public WriteAttribute {
public:
    WriteTestClusterNullableEnumAttr()
        : WriteAttribute("nullable-enum-attr")
    {
        AddArgument("attr-name", "nullable-enum-attr");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableEnumAttrWithValue:value
                                                  params:params
                                       completionHandler:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("TestCluster NullableEnumAttr write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterNullableEnumAttr : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableEnumAttr()
        : SubscribeAttribute("nullable-enum-attr")
    {
    }

    ~SubscribeAttributeTestClusterNullableEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableEnumAttrWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableEnumAttr response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableStruct
 */
class ReadTestClusterNullableStruct : public ReadAttribute {
public:
    ReadTestClusterNullableStruct()
        : ReadAttribute("nullable-struct")
    {
    }

    ~ReadTestClusterNullableStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableStructWithCompletionHandler:^(
            MTRTestClusterClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableStruct response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableStruct read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableStruct : public WriteAttribute {
public:
    WriteTestClusterNullableStruct()
        : WriteAttribute("nullable-struct")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "nullable-struct");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        MTRTestClusterClusterSimpleStruct * _Nullable value;
        if (mValue.IsNull()) {
            value = nil;
        } else {
            value = [MTRTestClusterClusterSimpleStruct new];
            value.a = [NSNumber numberWithUnsignedChar:mValue.Value().a];
            value.b = [NSNumber numberWithBool:mValue.Value().b];
            value.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mValue.Value().c)];
            value.d = [NSData dataWithBytes:mValue.Value().d.data() length:mValue.Value().d.size()];
            value.e = [[NSString alloc] initWithBytes:mValue.Value().e.data()
                                               length:mValue.Value().e.size()
                                             encoding:NSUTF8StringEncoding];
            value.f = [NSNumber numberWithUnsignedChar:mValue.Value().f.Raw()];
            value.g = [NSNumber numberWithFloat:mValue.Value().g];
            value.h = [NSNumber numberWithDouble:mValue.Value().h];
        }

        [cluster writeAttributeNullableStructWithValue:value
                                                params:params
                                     completionHandler:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster NullableStruct write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::Nullable<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::Nullable<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>> mComplex;
};

class SubscribeAttributeTestClusterNullableStruct : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableStruct()
        : SubscribeAttribute("nullable-struct")
    {
    }

    ~SubscribeAttributeTestClusterNullableStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableStructWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRTestClusterClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableStruct response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt8u
 */
class ReadTestClusterNullableRangeRestrictedInt8u : public ReadAttribute {
public:
    ReadTestClusterNullableRangeRestrictedInt8u()
        : ReadAttribute("nullable-range-restricted-int8u")
    {
    }

    ~ReadTestClusterNullableRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt8uWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableRangeRestrictedInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableRangeRestrictedInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableRangeRestrictedInt8u : public WriteAttribute {
public:
    WriteTestClusterNullableRangeRestrictedInt8u()
        : WriteAttribute("nullable-range-restricted-int8u")
    {
        AddArgument("attr-name", "nullable-range-restricted-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster
            writeAttributeNullableRangeRestrictedInt8uWithValue:value
                                                         params:params
                                              completionHandler:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("TestCluster NullableRangeRestrictedInt8u write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterNullableRangeRestrictedInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableRangeRestrictedInt8u()
        : SubscribeAttribute("nullable-range-restricted-int8u")
    {
    }

    ~SubscribeAttributeTestClusterNullableRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableRangeRestrictedInt8uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableRangeRestrictedInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt8s
 */
class ReadTestClusterNullableRangeRestrictedInt8s : public ReadAttribute {
public:
    ReadTestClusterNullableRangeRestrictedInt8s()
        : ReadAttribute("nullable-range-restricted-int8s")
    {
    }

    ~ReadTestClusterNullableRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004027) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt8sWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableRangeRestrictedInt8s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableRangeRestrictedInt8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableRangeRestrictedInt8s : public WriteAttribute {
public:
    WriteTestClusterNullableRangeRestrictedInt8s()
        : WriteAttribute("nullable-range-restricted-int8s")
    {
        AddArgument("attr-name", "nullable-range-restricted-int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithChar:mValue];

        [cluster
            writeAttributeNullableRangeRestrictedInt8sWithValue:value
                                                         params:params
                                              completionHandler:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("TestCluster NullableRangeRestrictedInt8s write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeTestClusterNullableRangeRestrictedInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableRangeRestrictedInt8s()
        : SubscribeAttribute("nullable-range-restricted-int8s")
    {
    }

    ~SubscribeAttributeTestClusterNullableRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableRangeRestrictedInt8sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableRangeRestrictedInt8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt16u
 */
class ReadTestClusterNullableRangeRestrictedInt16u : public ReadAttribute {
public:
    ReadTestClusterNullableRangeRestrictedInt16u()
        : ReadAttribute("nullable-range-restricted-int16u")
    {
    }

    ~ReadTestClusterNullableRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004028) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt16uWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableRangeRestrictedInt16u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableRangeRestrictedInt16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableRangeRestrictedInt16u : public WriteAttribute {
public:
    WriteTestClusterNullableRangeRestrictedInt16u()
        : WriteAttribute("nullable-range-restricted-int16u")
    {
        AddArgument("attr-name", "nullable-range-restricted-int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeNullableRangeRestrictedInt16uWithValue:value
                                                          params:params
                                               completionHandler:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("TestCluster NullableRangeRestrictedInt16u write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterNullableRangeRestrictedInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableRangeRestrictedInt16u()
        : SubscribeAttribute("nullable-range-restricted-int16u")
    {
    }

    ~SubscribeAttributeTestClusterNullableRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableRangeRestrictedInt16uWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableRangeRestrictedInt16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt16s
 */
class ReadTestClusterNullableRangeRestrictedInt16s : public ReadAttribute {
public:
    ReadTestClusterNullableRangeRestrictedInt16s()
        : ReadAttribute("nullable-range-restricted-int16s")
    {
    }

    ~ReadTestClusterNullableRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt16sWithCompletionHandler:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableRangeRestrictedInt16s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableRangeRestrictedInt16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableRangeRestrictedInt16s : public WriteAttribute {
public:
    WriteTestClusterNullableRangeRestrictedInt16s()
        : WriteAttribute("nullable-range-restricted-int16s")
    {
        AddArgument("attr-name", "nullable-range-restricted-int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithShort:mValue];

        [cluster
            writeAttributeNullableRangeRestrictedInt16sWithValue:value
                                                          params:params
                                               completionHandler:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("TestCluster NullableRangeRestrictedInt16s write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeTestClusterNullableRangeRestrictedInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableRangeRestrictedInt16s()
        : SubscribeAttribute("nullable-range-restricted-int16s")
    {
    }

    ~SubscribeAttributeTestClusterNullableRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeNullableRangeRestrictedInt16sWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableRangeRestrictedInt16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadTestClusterGeneratedCommandList : public ReadAttribute {
public:
    ReadTestClusterGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadTestClusterGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTestClusterGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeTestClusterGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeGeneratedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadTestClusterAcceptedCommandList : public ReadAttribute {
public:
    ReadTestClusterAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadTestClusterAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTestClusterAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeTestClusterAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAcceptedCommandListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadTestClusterAttributeList : public ReadAttribute {
public:
    ReadTestClusterAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadTestClusterAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTestClusterAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeTestClusterAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeAttributeListWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadTestClusterFeatureMap : public ReadAttribute {
public:
    ReadTestClusterFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadTestClusterFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTestClusterFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeTestClusterFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeFeatureMapWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadTestClusterClusterRevision : public ReadAttribute {
public:
    ReadTestClusterClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadTestClusterClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTestClusterClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeTestClusterClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                       endpoint:endpointId
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] init];
        params.keepPreviousSubscriptions
            = mKeepSubscriptions.HasValue() ? [NSNumber numberWithBool:mKeepSubscriptions.Value()] : nil;
        params.fabricFiltered = mFabricFiltered.HasValue() ? [NSNumber numberWithBool:mFabricFiltered.Value()] : nil;
        [cluster subscribeAttributeClusterRevisionWithMinInterval:[NSNumber numberWithUnsignedInt:mMinInterval]
            maxInterval:[NSNumber numberWithUnsignedInt:mMaxInterval]
            params:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Register all Clusters commands                                               |
\*----------------------------------------------------------------------------*/
void registerClusterIdentify(Commands & commands)
{
    using namespace chip::app::Clusters::Identify;

    const char * clusterName = "Identify";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<IdentifyIdentify>(), //
        make_unique<IdentifyTriggerEffect>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadIdentifyIdentifyTime>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteIdentifyIdentifyTime>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeIdentifyIdentifyTime>(), //
        make_unique<ReadIdentifyIdentifyType>(), //
        make_unique<SubscribeAttributeIdentifyIdentifyType>(), //
        make_unique<ReadIdentifyGeneratedCommandList>(), //
        make_unique<SubscribeAttributeIdentifyGeneratedCommandList>(), //
        make_unique<ReadIdentifyAcceptedCommandList>(), //
        make_unique<SubscribeAttributeIdentifyAcceptedCommandList>(), //
        make_unique<ReadIdentifyAttributeList>(), //
        make_unique<SubscribeAttributeIdentifyAttributeList>(), //
        make_unique<ReadIdentifyFeatureMap>(), //
        make_unique<SubscribeAttributeIdentifyFeatureMap>(), //
        make_unique<ReadIdentifyClusterRevision>(), //
        make_unique<SubscribeAttributeIdentifyClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterGroups(Commands & commands)
{
    using namespace chip::app::Clusters::Groups;

    const char * clusterName = "Groups";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<GroupsAddGroup>(), //
        make_unique<GroupsViewGroup>(), //
        make_unique<GroupsGetGroupMembership>(), //
        make_unique<GroupsRemoveGroup>(), //
        make_unique<GroupsRemoveAllGroups>(), //
        make_unique<GroupsAddGroupIfIdentifying>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadGroupsNameSupport>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeGroupsNameSupport>(), //
        make_unique<ReadGroupsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeGroupsGeneratedCommandList>(), //
        make_unique<ReadGroupsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeGroupsAcceptedCommandList>(), //
        make_unique<ReadGroupsAttributeList>(), //
        make_unique<SubscribeAttributeGroupsAttributeList>(), //
        make_unique<ReadGroupsFeatureMap>(), //
        make_unique<SubscribeAttributeGroupsFeatureMap>(), //
        make_unique<ReadGroupsClusterRevision>(), //
        make_unique<SubscribeAttributeGroupsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterScenes(Commands & commands)
{
    using namespace chip::app::Clusters::Scenes;

    const char * clusterName = "Scenes";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ScenesAddScene>(), //
        make_unique<ScenesViewScene>(), //
        make_unique<ScenesRemoveScene>(), //
        make_unique<ScenesRemoveAllScenes>(), //
        make_unique<ScenesStoreScene>(), //
        make_unique<ScenesRecallScene>(), //
        make_unique<ScenesGetSceneMembership>(), //
        make_unique<ScenesEnhancedAddScene>(), //
        make_unique<ScenesEnhancedViewScene>(), //
        make_unique<ScenesCopyScene>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadScenesSceneCount>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeScenesSceneCount>(), //
        make_unique<ReadScenesCurrentScene>(), //
        make_unique<SubscribeAttributeScenesCurrentScene>(), //
        make_unique<ReadScenesCurrentGroup>(), //
        make_unique<SubscribeAttributeScenesCurrentGroup>(), //
        make_unique<ReadScenesSceneValid>(), //
        make_unique<SubscribeAttributeScenesSceneValid>(), //
        make_unique<ReadScenesNameSupport>(), //
        make_unique<SubscribeAttributeScenesNameSupport>(), //
        make_unique<ReadScenesLastConfiguredBy>(), //
        make_unique<SubscribeAttributeScenesLastConfiguredBy>(), //
        make_unique<ReadScenesGeneratedCommandList>(), //
        make_unique<SubscribeAttributeScenesGeneratedCommandList>(), //
        make_unique<ReadScenesAcceptedCommandList>(), //
        make_unique<SubscribeAttributeScenesAcceptedCommandList>(), //
        make_unique<ReadScenesAttributeList>(), //
        make_unique<SubscribeAttributeScenesAttributeList>(), //
        make_unique<ReadScenesFeatureMap>(), //
        make_unique<SubscribeAttributeScenesFeatureMap>(), //
        make_unique<ReadScenesClusterRevision>(), //
        make_unique<SubscribeAttributeScenesClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOnOff(Commands & commands)
{
    using namespace chip::app::Clusters::OnOff;

    const char * clusterName = "OnOff";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<OnOffOff>(), //
        make_unique<OnOffOn>(), //
        make_unique<OnOffToggle>(), //
        make_unique<OnOffOffWithEffect>(), //
        make_unique<OnOffOnWithRecallGlobalScene>(), //
        make_unique<OnOffOnWithTimedOff>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOnOffOnOff>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOnOffOnOff>(), //
        make_unique<ReadOnOffGlobalSceneControl>(), //
        make_unique<SubscribeAttributeOnOffGlobalSceneControl>(), //
        make_unique<ReadOnOffOnTime>(), //
        make_unique<WriteOnOffOnTime>(), //
        make_unique<SubscribeAttributeOnOffOnTime>(), //
        make_unique<ReadOnOffOffWaitTime>(), //
        make_unique<WriteOnOffOffWaitTime>(), //
        make_unique<SubscribeAttributeOnOffOffWaitTime>(), //
        make_unique<ReadOnOffStartUpOnOff>(), //
        make_unique<WriteOnOffStartUpOnOff>(), //
        make_unique<SubscribeAttributeOnOffStartUpOnOff>(), //
        make_unique<ReadOnOffGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOnOffGeneratedCommandList>(), //
        make_unique<ReadOnOffAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOnOffAcceptedCommandList>(), //
        make_unique<ReadOnOffAttributeList>(), //
        make_unique<SubscribeAttributeOnOffAttributeList>(), //
        make_unique<ReadOnOffFeatureMap>(), //
        make_unique<SubscribeAttributeOnOffFeatureMap>(), //
        make_unique<ReadOnOffClusterRevision>(), //
        make_unique<SubscribeAttributeOnOffClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOnOffSwitchConfiguration(Commands & commands)
{
    using namespace chip::app::Clusters::OnOffSwitchConfiguration;

    const char * clusterName = "OnOffSwitchConfiguration";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOnOffSwitchConfigurationSwitchType>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationSwitchType>(), //
        make_unique<ReadOnOffSwitchConfigurationSwitchActions>(), //
        make_unique<WriteOnOffSwitchConfigurationSwitchActions>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationSwitchActions>(), //
        make_unique<ReadOnOffSwitchConfigurationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationGeneratedCommandList>(), //
        make_unique<ReadOnOffSwitchConfigurationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationAcceptedCommandList>(), //
        make_unique<ReadOnOffSwitchConfigurationAttributeList>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationAttributeList>(), //
        make_unique<ReadOnOffSwitchConfigurationFeatureMap>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationFeatureMap>(), //
        make_unique<ReadOnOffSwitchConfigurationClusterRevision>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterLevelControl(Commands & commands)
{
    using namespace chip::app::Clusters::LevelControl;

    const char * clusterName = "LevelControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<LevelControlMoveToLevel>(), //
        make_unique<LevelControlMove>(), //
        make_unique<LevelControlStep>(), //
        make_unique<LevelControlStop>(), //
        make_unique<LevelControlMoveToLevelWithOnOff>(), //
        make_unique<LevelControlMoveWithOnOff>(), //
        make_unique<LevelControlStepWithOnOff>(), //
        make_unique<LevelControlStopWithOnOff>(), //
        make_unique<LevelControlMoveToClosestFrequency>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadLevelControlCurrentLevel>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeLevelControlCurrentLevel>(), //
        make_unique<ReadLevelControlRemainingTime>(), //
        make_unique<SubscribeAttributeLevelControlRemainingTime>(), //
        make_unique<ReadLevelControlMinLevel>(), //
        make_unique<SubscribeAttributeLevelControlMinLevel>(), //
        make_unique<ReadLevelControlMaxLevel>(), //
        make_unique<SubscribeAttributeLevelControlMaxLevel>(), //
        make_unique<ReadLevelControlCurrentFrequency>(), //
        make_unique<SubscribeAttributeLevelControlCurrentFrequency>(), //
        make_unique<ReadLevelControlMinFrequency>(), //
        make_unique<SubscribeAttributeLevelControlMinFrequency>(), //
        make_unique<ReadLevelControlMaxFrequency>(), //
        make_unique<SubscribeAttributeLevelControlMaxFrequency>(), //
        make_unique<ReadLevelControlOptions>(), //
        make_unique<WriteLevelControlOptions>(), //
        make_unique<SubscribeAttributeLevelControlOptions>(), //
        make_unique<ReadLevelControlOnOffTransitionTime>(), //
        make_unique<WriteLevelControlOnOffTransitionTime>(), //
        make_unique<SubscribeAttributeLevelControlOnOffTransitionTime>(), //
        make_unique<ReadLevelControlOnLevel>(), //
        make_unique<WriteLevelControlOnLevel>(), //
        make_unique<SubscribeAttributeLevelControlOnLevel>(), //
        make_unique<ReadLevelControlOnTransitionTime>(), //
        make_unique<WriteLevelControlOnTransitionTime>(), //
        make_unique<SubscribeAttributeLevelControlOnTransitionTime>(), //
        make_unique<ReadLevelControlOffTransitionTime>(), //
        make_unique<WriteLevelControlOffTransitionTime>(), //
        make_unique<SubscribeAttributeLevelControlOffTransitionTime>(), //
        make_unique<ReadLevelControlDefaultMoveRate>(), //
        make_unique<WriteLevelControlDefaultMoveRate>(), //
        make_unique<SubscribeAttributeLevelControlDefaultMoveRate>(), //
        make_unique<ReadLevelControlStartUpCurrentLevel>(), //
        make_unique<WriteLevelControlStartUpCurrentLevel>(), //
        make_unique<SubscribeAttributeLevelControlStartUpCurrentLevel>(), //
        make_unique<ReadLevelControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeLevelControlGeneratedCommandList>(), //
        make_unique<ReadLevelControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeLevelControlAcceptedCommandList>(), //
        make_unique<ReadLevelControlAttributeList>(), //
        make_unique<SubscribeAttributeLevelControlAttributeList>(), //
        make_unique<ReadLevelControlFeatureMap>(), //
        make_unique<SubscribeAttributeLevelControlFeatureMap>(), //
        make_unique<ReadLevelControlClusterRevision>(), //
        make_unique<SubscribeAttributeLevelControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBinaryInputBasic(Commands & commands)
{
    using namespace chip::app::Clusters::BinaryInputBasic;

    const char * clusterName = "BinaryInputBasic";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBinaryInputBasicActiveText>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteBinaryInputBasicActiveText>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBinaryInputBasicActiveText>(), //
        make_unique<ReadBinaryInputBasicDescription>(), //
        make_unique<WriteBinaryInputBasicDescription>(), //
        make_unique<SubscribeAttributeBinaryInputBasicDescription>(), //
        make_unique<ReadBinaryInputBasicInactiveText>(), //
        make_unique<WriteBinaryInputBasicInactiveText>(), //
        make_unique<SubscribeAttributeBinaryInputBasicInactiveText>(), //
        make_unique<ReadBinaryInputBasicOutOfService>(), //
        make_unique<WriteBinaryInputBasicOutOfService>(), //
        make_unique<SubscribeAttributeBinaryInputBasicOutOfService>(), //
        make_unique<ReadBinaryInputBasicPolarity>(), //
        make_unique<SubscribeAttributeBinaryInputBasicPolarity>(), //
        make_unique<ReadBinaryInputBasicPresentValue>(), //
        make_unique<WriteBinaryInputBasicPresentValue>(), //
        make_unique<SubscribeAttributeBinaryInputBasicPresentValue>(), //
        make_unique<ReadBinaryInputBasicReliability>(), //
        make_unique<WriteBinaryInputBasicReliability>(), //
        make_unique<SubscribeAttributeBinaryInputBasicReliability>(), //
        make_unique<ReadBinaryInputBasicStatusFlags>(), //
        make_unique<SubscribeAttributeBinaryInputBasicStatusFlags>(), //
        make_unique<ReadBinaryInputBasicApplicationType>(), //
        make_unique<SubscribeAttributeBinaryInputBasicApplicationType>(), //
        make_unique<ReadBinaryInputBasicGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBinaryInputBasicGeneratedCommandList>(), //
        make_unique<ReadBinaryInputBasicAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBinaryInputBasicAcceptedCommandList>(), //
        make_unique<ReadBinaryInputBasicAttributeList>(), //
        make_unique<SubscribeAttributeBinaryInputBasicAttributeList>(), //
        make_unique<ReadBinaryInputBasicFeatureMap>(), //
        make_unique<SubscribeAttributeBinaryInputBasicFeatureMap>(), //
        make_unique<ReadBinaryInputBasicClusterRevision>(), //
        make_unique<SubscribeAttributeBinaryInputBasicClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterDescriptor(Commands & commands)
{
    using namespace chip::app::Clusters::Descriptor;

    const char * clusterName = "Descriptor";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadDescriptorDeviceList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeDescriptorDeviceList>(), //
        make_unique<ReadDescriptorServerList>(), //
        make_unique<SubscribeAttributeDescriptorServerList>(), //
        make_unique<ReadDescriptorClientList>(), //
        make_unique<SubscribeAttributeDescriptorClientList>(), //
        make_unique<ReadDescriptorPartsList>(), //
        make_unique<SubscribeAttributeDescriptorPartsList>(), //
        make_unique<ReadDescriptorGeneratedCommandList>(), //
        make_unique<SubscribeAttributeDescriptorGeneratedCommandList>(), //
        make_unique<ReadDescriptorAcceptedCommandList>(), //
        make_unique<SubscribeAttributeDescriptorAcceptedCommandList>(), //
        make_unique<ReadDescriptorAttributeList>(), //
        make_unique<SubscribeAttributeDescriptorAttributeList>(), //
        make_unique<ReadDescriptorFeatureMap>(), //
        make_unique<SubscribeAttributeDescriptorFeatureMap>(), //
        make_unique<ReadDescriptorClusterRevision>(), //
        make_unique<SubscribeAttributeDescriptorClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBinding(Commands & commands)
{
    using namespace chip::app::Clusters::Binding;

    const char * clusterName = "Binding";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBindingBinding>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteBindingBinding>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBindingBinding>(), //
        make_unique<ReadBindingGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBindingGeneratedCommandList>(), //
        make_unique<ReadBindingAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBindingAcceptedCommandList>(), //
        make_unique<ReadBindingAttributeList>(), //
        make_unique<SubscribeAttributeBindingAttributeList>(), //
        make_unique<ReadBindingFeatureMap>(), //
        make_unique<SubscribeAttributeBindingFeatureMap>(), //
        make_unique<ReadBindingClusterRevision>(), //
        make_unique<SubscribeAttributeBindingClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterAccessControl(Commands & commands)
{
    using namespace chip::app::Clusters::AccessControl;

    const char * clusterName = "AccessControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadAccessControlAcl>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteAccessControlAcl>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeAccessControlAcl>(), //
        make_unique<ReadAccessControlExtension>(), //
        make_unique<WriteAccessControlExtension>(), //
        make_unique<SubscribeAttributeAccessControlExtension>(), //
        make_unique<ReadAccessControlSubjectsPerAccessControlEntry>(), //
        make_unique<SubscribeAttributeAccessControlSubjectsPerAccessControlEntry>(), //
        make_unique<ReadAccessControlTargetsPerAccessControlEntry>(), //
        make_unique<SubscribeAttributeAccessControlTargetsPerAccessControlEntry>(), //
        make_unique<ReadAccessControlAccessControlEntriesPerFabric>(), //
        make_unique<SubscribeAttributeAccessControlAccessControlEntriesPerFabric>(), //
        make_unique<ReadAccessControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeAccessControlGeneratedCommandList>(), //
        make_unique<ReadAccessControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeAccessControlAcceptedCommandList>(), //
        make_unique<ReadAccessControlAttributeList>(), //
        make_unique<SubscribeAttributeAccessControlAttributeList>(), //
        make_unique<ReadAccessControlFeatureMap>(), //
        make_unique<SubscribeAttributeAccessControlFeatureMap>(), //
        make_unique<ReadAccessControlClusterRevision>(), //
        make_unique<SubscribeAttributeAccessControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBridgedActions(Commands & commands)
{
    using namespace chip::app::Clusters::BridgedActions;

    const char * clusterName = "BridgedActions";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<BridgedActionsInstantAction>(), //
        make_unique<BridgedActionsInstantActionWithTransition>(), //
        make_unique<BridgedActionsStartAction>(), //
        make_unique<BridgedActionsStartActionWithDuration>(), //
        make_unique<BridgedActionsStopAction>(), //
        make_unique<BridgedActionsPauseAction>(), //
        make_unique<BridgedActionsPauseActionWithDuration>(), //
        make_unique<BridgedActionsResumeAction>(), //
        make_unique<BridgedActionsEnableAction>(), //
        make_unique<BridgedActionsEnableActionWithDuration>(), //
        make_unique<BridgedActionsDisableAction>(), //
        make_unique<BridgedActionsDisableActionWithDuration>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBridgedActionsActionList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBridgedActionsActionList>(), //
        make_unique<ReadBridgedActionsEndpointList>(), //
        make_unique<SubscribeAttributeBridgedActionsEndpointList>(), //
        make_unique<ReadBridgedActionsSetupUrl>(), //
        make_unique<SubscribeAttributeBridgedActionsSetupUrl>(), //
        make_unique<ReadBridgedActionsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBridgedActionsGeneratedCommandList>(), //
        make_unique<ReadBridgedActionsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBridgedActionsAcceptedCommandList>(), //
        make_unique<ReadBridgedActionsAttributeList>(), //
        make_unique<SubscribeAttributeBridgedActionsAttributeList>(), //
        make_unique<ReadBridgedActionsFeatureMap>(), //
        make_unique<SubscribeAttributeBridgedActionsFeatureMap>(), //
        make_unique<ReadBridgedActionsClusterRevision>(), //
        make_unique<SubscribeAttributeBridgedActionsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBasic(Commands & commands)
{
    using namespace chip::app::Clusters::Basic;

    const char * clusterName = "Basic";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<BasicMfgSpecificPing>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBasicDataModelRevision>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBasicDataModelRevision>(), //
        make_unique<ReadBasicVendorName>(), //
        make_unique<SubscribeAttributeBasicVendorName>(), //
        make_unique<ReadBasicVendorID>(), //
        make_unique<SubscribeAttributeBasicVendorID>(), //
        make_unique<ReadBasicProductName>(), //
        make_unique<SubscribeAttributeBasicProductName>(), //
        make_unique<ReadBasicProductID>(), //
        make_unique<SubscribeAttributeBasicProductID>(), //
        make_unique<ReadBasicNodeLabel>(), //
        make_unique<WriteBasicNodeLabel>(), //
        make_unique<SubscribeAttributeBasicNodeLabel>(), //
        make_unique<ReadBasicLocation>(), //
        make_unique<WriteBasicLocation>(), //
        make_unique<SubscribeAttributeBasicLocation>(), //
        make_unique<ReadBasicHardwareVersion>(), //
        make_unique<SubscribeAttributeBasicHardwareVersion>(), //
        make_unique<ReadBasicHardwareVersionString>(), //
        make_unique<SubscribeAttributeBasicHardwareVersionString>(), //
        make_unique<ReadBasicSoftwareVersion>(), //
        make_unique<SubscribeAttributeBasicSoftwareVersion>(), //
        make_unique<ReadBasicSoftwareVersionString>(), //
        make_unique<SubscribeAttributeBasicSoftwareVersionString>(), //
        make_unique<ReadBasicManufacturingDate>(), //
        make_unique<SubscribeAttributeBasicManufacturingDate>(), //
        make_unique<ReadBasicPartNumber>(), //
        make_unique<SubscribeAttributeBasicPartNumber>(), //
        make_unique<ReadBasicProductURL>(), //
        make_unique<SubscribeAttributeBasicProductURL>(), //
        make_unique<ReadBasicProductLabel>(), //
        make_unique<SubscribeAttributeBasicProductLabel>(), //
        make_unique<ReadBasicSerialNumber>(), //
        make_unique<SubscribeAttributeBasicSerialNumber>(), //
        make_unique<ReadBasicLocalConfigDisabled>(), //
        make_unique<WriteBasicLocalConfigDisabled>(), //
        make_unique<SubscribeAttributeBasicLocalConfigDisabled>(), //
        make_unique<ReadBasicReachable>(), //
        make_unique<SubscribeAttributeBasicReachable>(), //
        make_unique<ReadBasicUniqueID>(), //
        make_unique<SubscribeAttributeBasicUniqueID>(), //
        make_unique<ReadBasicCapabilityMinima>(), //
        make_unique<SubscribeAttributeBasicCapabilityMinima>(), //
        make_unique<ReadBasicGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBasicGeneratedCommandList>(), //
        make_unique<ReadBasicAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBasicAcceptedCommandList>(), //
        make_unique<ReadBasicAttributeList>(), //
        make_unique<SubscribeAttributeBasicAttributeList>(), //
        make_unique<ReadBasicFeatureMap>(), //
        make_unique<SubscribeAttributeBasicFeatureMap>(), //
        make_unique<ReadBasicClusterRevision>(), //
        make_unique<SubscribeAttributeBasicClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOtaSoftwareUpdateProvider(Commands & commands)
{
    using namespace chip::app::Clusters::OtaSoftwareUpdateProvider;

    const char * clusterName = "OtaSoftwareUpdateProvider";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<OtaSoftwareUpdateProviderQueryImage>(), //
        make_unique<OtaSoftwareUpdateProviderApplyUpdateRequest>(), //
        make_unique<OtaSoftwareUpdateProviderNotifyUpdateApplied>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOtaSoftwareUpdateProviderGeneratedCommandList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderGeneratedCommandList>(), //
        make_unique<ReadOtaSoftwareUpdateProviderAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderAcceptedCommandList>(), //
        make_unique<ReadOtaSoftwareUpdateProviderAttributeList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderAttributeList>(), //
        make_unique<ReadOtaSoftwareUpdateProviderFeatureMap>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderFeatureMap>(), //
        make_unique<ReadOtaSoftwareUpdateProviderClusterRevision>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOtaSoftwareUpdateRequestor(Commands & commands)
{
    using namespace chip::app::Clusters::OtaSoftwareUpdateRequestor;

    const char * clusterName = "OtaSoftwareUpdateRequestor";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<OtaSoftwareUpdateRequestorAnnounceOtaProvider>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOtaSoftwareUpdateRequestorDefaultOtaProviders>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteOtaSoftwareUpdateRequestorDefaultOtaProviders>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorDefaultOtaProviders>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorUpdatePossible>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorUpdatePossible>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorUpdateState>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorUpdateState>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorUpdateStateProgress>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorUpdateStateProgress>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorGeneratedCommandList>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorAcceptedCommandList>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorAttributeList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorAttributeList>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorFeatureMap>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorFeatureMap>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorClusterRevision>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterLocalizationConfiguration(Commands & commands)
{
    using namespace chip::app::Clusters::LocalizationConfiguration;

    const char * clusterName = "LocalizationConfiguration";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadLocalizationConfigurationActiveLocale>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteLocalizationConfigurationActiveLocale>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeLocalizationConfigurationActiveLocale>(), //
        make_unique<ReadLocalizationConfigurationSupportedLocales>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationSupportedLocales>(), //
        make_unique<ReadLocalizationConfigurationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationGeneratedCommandList>(), //
        make_unique<ReadLocalizationConfigurationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationAcceptedCommandList>(), //
        make_unique<ReadLocalizationConfigurationAttributeList>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationAttributeList>(), //
        make_unique<ReadLocalizationConfigurationFeatureMap>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationFeatureMap>(), //
        make_unique<ReadLocalizationConfigurationClusterRevision>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterTimeFormatLocalization(Commands & commands)
{
    using namespace chip::app::Clusters::TimeFormatLocalization;

    const char * clusterName = "TimeFormatLocalization";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadTimeFormatLocalizationHourFormat>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteTimeFormatLocalizationHourFormat>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeTimeFormatLocalizationHourFormat>(), //
        make_unique<ReadTimeFormatLocalizationActiveCalendarType>(), //
        make_unique<WriteTimeFormatLocalizationActiveCalendarType>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationActiveCalendarType>(), //
        make_unique<ReadTimeFormatLocalizationSupportedCalendarTypes>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationSupportedCalendarTypes>(), //
        make_unique<ReadTimeFormatLocalizationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationGeneratedCommandList>(), //
        make_unique<ReadTimeFormatLocalizationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationAcceptedCommandList>(), //
        make_unique<ReadTimeFormatLocalizationAttributeList>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationAttributeList>(), //
        make_unique<ReadTimeFormatLocalizationFeatureMap>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationFeatureMap>(), //
        make_unique<ReadTimeFormatLocalizationClusterRevision>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterUnitLocalization(Commands & commands)
{
    using namespace chip::app::Clusters::UnitLocalization;

    const char * clusterName = "UnitLocalization";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadUnitLocalizationTemperatureUnit>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteUnitLocalizationTemperatureUnit>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeUnitLocalizationTemperatureUnit>(), //
        make_unique<ReadUnitLocalizationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeUnitLocalizationGeneratedCommandList>(), //
        make_unique<ReadUnitLocalizationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeUnitLocalizationAcceptedCommandList>(), //
        make_unique<ReadUnitLocalizationAttributeList>(), //
        make_unique<SubscribeAttributeUnitLocalizationAttributeList>(), //
        make_unique<ReadUnitLocalizationFeatureMap>(), //
        make_unique<SubscribeAttributeUnitLocalizationFeatureMap>(), //
        make_unique<ReadUnitLocalizationClusterRevision>(), //
        make_unique<SubscribeAttributeUnitLocalizationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterPowerSourceConfiguration(Commands & commands)
{
    using namespace chip::app::Clusters::PowerSourceConfiguration;

    const char * clusterName = "PowerSourceConfiguration";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadPowerSourceConfigurationSources>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributePowerSourceConfigurationSources>(), //
        make_unique<ReadPowerSourceConfigurationGeneratedCommandList>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationGeneratedCommandList>(), //
        make_unique<ReadPowerSourceConfigurationAcceptedCommandList>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationAcceptedCommandList>(), //
        make_unique<ReadPowerSourceConfigurationAttributeList>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationAttributeList>(), //
        make_unique<ReadPowerSourceConfigurationFeatureMap>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationFeatureMap>(), //
        make_unique<ReadPowerSourceConfigurationClusterRevision>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterPowerSource(Commands & commands)
{
    using namespace chip::app::Clusters::PowerSource;

    const char * clusterName = "PowerSource";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadPowerSourceStatus>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributePowerSourceStatus>(), //
        make_unique<ReadPowerSourceOrder>(), //
        make_unique<SubscribeAttributePowerSourceOrder>(), //
        make_unique<ReadPowerSourceDescription>(), //
        make_unique<SubscribeAttributePowerSourceDescription>(), //
        make_unique<ReadPowerSourceWiredAssessedInputVoltage>(), //
        make_unique<SubscribeAttributePowerSourceWiredAssessedInputVoltage>(), //
        make_unique<ReadPowerSourceWiredAssessedInputFrequency>(), //
        make_unique<SubscribeAttributePowerSourceWiredAssessedInputFrequency>(), //
        make_unique<ReadPowerSourceWiredCurrentType>(), //
        make_unique<SubscribeAttributePowerSourceWiredCurrentType>(), //
        make_unique<ReadPowerSourceWiredAssessedCurrent>(), //
        make_unique<SubscribeAttributePowerSourceWiredAssessedCurrent>(), //
        make_unique<ReadPowerSourceWiredNominalVoltage>(), //
        make_unique<SubscribeAttributePowerSourceWiredNominalVoltage>(), //
        make_unique<ReadPowerSourceWiredMaximumCurrent>(), //
        make_unique<SubscribeAttributePowerSourceWiredMaximumCurrent>(), //
        make_unique<ReadPowerSourceWiredPresent>(), //
        make_unique<SubscribeAttributePowerSourceWiredPresent>(), //
        make_unique<ReadPowerSourceActiveWiredFaults>(), //
        make_unique<SubscribeAttributePowerSourceActiveWiredFaults>(), //
        make_unique<ReadPowerSourceBatVoltage>(), //
        make_unique<SubscribeAttributePowerSourceBatVoltage>(), //
        make_unique<ReadPowerSourceBatPercentRemaining>(), //
        make_unique<SubscribeAttributePowerSourceBatPercentRemaining>(), //
        make_unique<ReadPowerSourceBatTimeRemaining>(), //
        make_unique<SubscribeAttributePowerSourceBatTimeRemaining>(), //
        make_unique<ReadPowerSourceBatChargeLevel>(), //
        make_unique<SubscribeAttributePowerSourceBatChargeLevel>(), //
        make_unique<ReadPowerSourceBatReplacementNeeded>(), //
        make_unique<SubscribeAttributePowerSourceBatReplacementNeeded>(), //
        make_unique<ReadPowerSourceBatReplaceability>(), //
        make_unique<SubscribeAttributePowerSourceBatReplaceability>(), //
        make_unique<ReadPowerSourceBatPresent>(), //
        make_unique<SubscribeAttributePowerSourceBatPresent>(), //
        make_unique<ReadPowerSourceActiveBatFaults>(), //
        make_unique<SubscribeAttributePowerSourceActiveBatFaults>(), //
        make_unique<ReadPowerSourceBatReplacementDescription>(), //
        make_unique<SubscribeAttributePowerSourceBatReplacementDescription>(), //
        make_unique<ReadPowerSourceBatCommonDesignation>(), //
        make_unique<SubscribeAttributePowerSourceBatCommonDesignation>(), //
        make_unique<ReadPowerSourceBatANSIDesignation>(), //
        make_unique<SubscribeAttributePowerSourceBatANSIDesignation>(), //
        make_unique<ReadPowerSourceBatIECDesignation>(), //
        make_unique<SubscribeAttributePowerSourceBatIECDesignation>(), //
        make_unique<ReadPowerSourceBatApprovedChemistry>(), //
        make_unique<SubscribeAttributePowerSourceBatApprovedChemistry>(), //
        make_unique<ReadPowerSourceBatCapacity>(), //
        make_unique<SubscribeAttributePowerSourceBatCapacity>(), //
        make_unique<ReadPowerSourceBatQuantity>(), //
        make_unique<SubscribeAttributePowerSourceBatQuantity>(), //
        make_unique<ReadPowerSourceBatChargeState>(), //
        make_unique<SubscribeAttributePowerSourceBatChargeState>(), //
        make_unique<ReadPowerSourceBatTimeToFullCharge>(), //
        make_unique<SubscribeAttributePowerSourceBatTimeToFullCharge>(), //
        make_unique<ReadPowerSourceBatFunctionalWhileCharging>(), //
        make_unique<SubscribeAttributePowerSourceBatFunctionalWhileCharging>(), //
        make_unique<ReadPowerSourceBatChargingCurrent>(), //
        make_unique<SubscribeAttributePowerSourceBatChargingCurrent>(), //
        make_unique<ReadPowerSourceActiveBatChargeFaults>(), //
        make_unique<SubscribeAttributePowerSourceActiveBatChargeFaults>(), //
        make_unique<ReadPowerSourceGeneratedCommandList>(), //
        make_unique<SubscribeAttributePowerSourceGeneratedCommandList>(), //
        make_unique<ReadPowerSourceAcceptedCommandList>(), //
        make_unique<SubscribeAttributePowerSourceAcceptedCommandList>(), //
        make_unique<ReadPowerSourceAttributeList>(), //
        make_unique<SubscribeAttributePowerSourceAttributeList>(), //
        make_unique<ReadPowerSourceFeatureMap>(), //
        make_unique<SubscribeAttributePowerSourceFeatureMap>(), //
        make_unique<ReadPowerSourceClusterRevision>(), //
        make_unique<SubscribeAttributePowerSourceClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterGeneralCommissioning(Commands & commands)
{
    using namespace chip::app::Clusters::GeneralCommissioning;

    const char * clusterName = "GeneralCommissioning";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<GeneralCommissioningArmFailSafe>(), //
        make_unique<GeneralCommissioningSetRegulatoryConfig>(), //
        make_unique<GeneralCommissioningCommissioningComplete>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadGeneralCommissioningBreadcrumb>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteGeneralCommissioningBreadcrumb>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeGeneralCommissioningBreadcrumb>(), //
        make_unique<ReadGeneralCommissioningBasicCommissioningInfo>(), //
        make_unique<SubscribeAttributeGeneralCommissioningBasicCommissioningInfo>(), //
        make_unique<ReadGeneralCommissioningRegulatoryConfig>(), //
        make_unique<SubscribeAttributeGeneralCommissioningRegulatoryConfig>(), //
        make_unique<ReadGeneralCommissioningLocationCapability>(), //
        make_unique<SubscribeAttributeGeneralCommissioningLocationCapability>(), //
        make_unique<ReadGeneralCommissioningSupportsConcurrentConnection>(), //
        make_unique<SubscribeAttributeGeneralCommissioningSupportsConcurrentConnection>(), //
        make_unique<ReadGeneralCommissioningGeneratedCommandList>(), //
        make_unique<SubscribeAttributeGeneralCommissioningGeneratedCommandList>(), //
        make_unique<ReadGeneralCommissioningAcceptedCommandList>(), //
        make_unique<SubscribeAttributeGeneralCommissioningAcceptedCommandList>(), //
        make_unique<ReadGeneralCommissioningAttributeList>(), //
        make_unique<SubscribeAttributeGeneralCommissioningAttributeList>(), //
        make_unique<ReadGeneralCommissioningFeatureMap>(), //
        make_unique<SubscribeAttributeGeneralCommissioningFeatureMap>(), //
        make_unique<ReadGeneralCommissioningClusterRevision>(), //
        make_unique<SubscribeAttributeGeneralCommissioningClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterNetworkCommissioning(Commands & commands)
{
    using namespace chip::app::Clusters::NetworkCommissioning;

    const char * clusterName = "NetworkCommissioning";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<NetworkCommissioningScanNetworks>(), //
        make_unique<NetworkCommissioningAddOrUpdateWiFiNetwork>(), //
        make_unique<NetworkCommissioningAddOrUpdateThreadNetwork>(), //
        make_unique<NetworkCommissioningRemoveNetwork>(), //
        make_unique<NetworkCommissioningConnectNetwork>(), //
        make_unique<NetworkCommissioningReorderNetwork>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadNetworkCommissioningMaxNetworks>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeNetworkCommissioningMaxNetworks>(), //
        make_unique<ReadNetworkCommissioningNetworks>(), //
        make_unique<SubscribeAttributeNetworkCommissioningNetworks>(), //
        make_unique<ReadNetworkCommissioningScanMaxTimeSeconds>(), //
        make_unique<SubscribeAttributeNetworkCommissioningScanMaxTimeSeconds>(), //
        make_unique<ReadNetworkCommissioningConnectMaxTimeSeconds>(), //
        make_unique<SubscribeAttributeNetworkCommissioningConnectMaxTimeSeconds>(), //
        make_unique<ReadNetworkCommissioningInterfaceEnabled>(), //
        make_unique<WriteNetworkCommissioningInterfaceEnabled>(), //
        make_unique<SubscribeAttributeNetworkCommissioningInterfaceEnabled>(), //
        make_unique<ReadNetworkCommissioningLastNetworkingStatus>(), //
        make_unique<SubscribeAttributeNetworkCommissioningLastNetworkingStatus>(), //
        make_unique<ReadNetworkCommissioningLastNetworkID>(), //
        make_unique<SubscribeAttributeNetworkCommissioningLastNetworkID>(), //
        make_unique<ReadNetworkCommissioningLastConnectErrorValue>(), //
        make_unique<SubscribeAttributeNetworkCommissioningLastConnectErrorValue>(), //
        make_unique<ReadNetworkCommissioningGeneratedCommandList>(), //
        make_unique<SubscribeAttributeNetworkCommissioningGeneratedCommandList>(), //
        make_unique<ReadNetworkCommissioningAcceptedCommandList>(), //
        make_unique<SubscribeAttributeNetworkCommissioningAcceptedCommandList>(), //
        make_unique<ReadNetworkCommissioningAttributeList>(), //
        make_unique<SubscribeAttributeNetworkCommissioningAttributeList>(), //
        make_unique<ReadNetworkCommissioningFeatureMap>(), //
        make_unique<SubscribeAttributeNetworkCommissioningFeatureMap>(), //
        make_unique<ReadNetworkCommissioningClusterRevision>(), //
        make_unique<SubscribeAttributeNetworkCommissioningClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterDiagnosticLogs(Commands & commands)
{
    using namespace chip::app::Clusters::DiagnosticLogs;

    const char * clusterName = "DiagnosticLogs";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<DiagnosticLogsRetrieveLogsRequest>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadDiagnosticLogsGeneratedCommandList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeDiagnosticLogsGeneratedCommandList>(), //
        make_unique<ReadDiagnosticLogsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeDiagnosticLogsAcceptedCommandList>(), //
        make_unique<ReadDiagnosticLogsAttributeList>(), //
        make_unique<SubscribeAttributeDiagnosticLogsAttributeList>(), //
        make_unique<ReadDiagnosticLogsFeatureMap>(), //
        make_unique<SubscribeAttributeDiagnosticLogsFeatureMap>(), //
        make_unique<ReadDiagnosticLogsClusterRevision>(), //
        make_unique<SubscribeAttributeDiagnosticLogsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterGeneralDiagnostics(Commands & commands)
{
    using namespace chip::app::Clusters::GeneralDiagnostics;

    const char * clusterName = "GeneralDiagnostics";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<GeneralDiagnosticsTestEventTrigger>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadGeneralDiagnosticsNetworkInterfaces>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeGeneralDiagnosticsNetworkInterfaces>(), //
        make_unique<ReadGeneralDiagnosticsRebootCount>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsRebootCount>(), //
        make_unique<ReadGeneralDiagnosticsUpTime>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsUpTime>(), //
        make_unique<ReadGeneralDiagnosticsTotalOperationalHours>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsTotalOperationalHours>(), //
        make_unique<ReadGeneralDiagnosticsBootReasons>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsBootReasons>(), //
        make_unique<ReadGeneralDiagnosticsActiveHardwareFaults>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsActiveHardwareFaults>(), //
        make_unique<ReadGeneralDiagnosticsActiveRadioFaults>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsActiveRadioFaults>(), //
        make_unique<ReadGeneralDiagnosticsActiveNetworkFaults>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsActiveNetworkFaults>(), //
        make_unique<ReadGeneralDiagnosticsTestEventTriggersEnabled>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsTestEventTriggersEnabled>(), //
        make_unique<ReadGeneralDiagnosticsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsGeneratedCommandList>(), //
        make_unique<ReadGeneralDiagnosticsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsAcceptedCommandList>(), //
        make_unique<ReadGeneralDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsAttributeList>(), //
        make_unique<ReadGeneralDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsFeatureMap>(), //
        make_unique<ReadGeneralDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterSoftwareDiagnostics(Commands & commands)
{
    using namespace chip::app::Clusters::SoftwareDiagnostics;

    const char * clusterName = "SoftwareDiagnostics";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<SoftwareDiagnosticsResetWatermarks>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadSoftwareDiagnosticsThreadMetrics>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsThreadMetrics>(), //
        make_unique<ReadSoftwareDiagnosticsCurrentHeapFree>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsCurrentHeapFree>(), //
        make_unique<ReadSoftwareDiagnosticsCurrentHeapUsed>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsCurrentHeapUsed>(), //
        make_unique<ReadSoftwareDiagnosticsCurrentHeapHighWatermark>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsCurrentHeapHighWatermark>(), //
        make_unique<ReadSoftwareDiagnosticsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsGeneratedCommandList>(), //
        make_unique<ReadSoftwareDiagnosticsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsAcceptedCommandList>(), //
        make_unique<ReadSoftwareDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsAttributeList>(), //
        make_unique<ReadSoftwareDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsFeatureMap>(), //
        make_unique<ReadSoftwareDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterThreadNetworkDiagnostics(Commands & commands)
{
    using namespace chip::app::Clusters::ThreadNetworkDiagnostics;

    const char * clusterName = "ThreadNetworkDiagnostics";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ThreadNetworkDiagnosticsResetCounts>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadThreadNetworkDiagnosticsChannel>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsChannel>(), //
        make_unique<ReadThreadNetworkDiagnosticsRoutingRole>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRoutingRole>(), //
        make_unique<ReadThreadNetworkDiagnosticsNetworkName>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsNetworkName>(), //
        make_unique<ReadThreadNetworkDiagnosticsPanId>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsPanId>(), //
        make_unique<ReadThreadNetworkDiagnosticsExtendedPanId>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsExtendedPanId>(), //
        make_unique<ReadThreadNetworkDiagnosticsMeshLocalPrefix>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsMeshLocalPrefix>(), //
        make_unique<ReadThreadNetworkDiagnosticsOverrunCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsOverrunCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsNeighborTableList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsNeighborTableList>(), //
        make_unique<ReadThreadNetworkDiagnosticsRouteTableList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRouteTableList>(), //
        make_unique<ReadThreadNetworkDiagnosticsPartitionId>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsPartitionId>(), //
        make_unique<ReadThreadNetworkDiagnosticsWeighting>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsWeighting>(), //
        make_unique<ReadThreadNetworkDiagnosticsDataVersion>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsDataVersion>(), //
        make_unique<ReadThreadNetworkDiagnosticsStableDataVersion>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsStableDataVersion>(), //
        make_unique<ReadThreadNetworkDiagnosticsLeaderRouterId>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsLeaderRouterId>(), //
        make_unique<ReadThreadNetworkDiagnosticsDetachedRoleCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsDetachedRoleCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsChildRoleCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsChildRoleCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRouterRoleCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRouterRoleCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsLeaderRoleCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsLeaderRoleCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsAttachAttemptCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsAttachAttemptCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsPartitionIdChangeCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsPartitionIdChangeCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsParentChangeCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsParentChangeCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxTotalCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxTotalCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxUnicastCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxUnicastCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxBroadcastCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxBroadcastCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxAckRequestedCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxAckRequestedCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxAckedCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxAckedCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxNoAckRequestedCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxNoAckRequestedCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxDataCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxDataCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxDataPollCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxDataPollCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxBeaconCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxBeaconCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxBeaconRequestCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxBeaconRequestCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxOtherCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxOtherCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxRetryCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxRetryCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxErrCcaCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxErrCcaCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxErrAbortCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxErrAbortCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxErrBusyChannelCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxErrBusyChannelCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxTotalCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxTotalCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxUnicastCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxUnicastCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxBroadcastCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxBroadcastCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxDataCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxDataCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxDataPollCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxDataPollCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxBeaconCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxBeaconCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxBeaconRequestCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxBeaconRequestCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxOtherCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxOtherCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxAddressFilteredCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxAddressFilteredCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxDestAddrFilteredCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxDestAddrFilteredCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxDuplicatedCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxDuplicatedCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrNoFrameCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrNoFrameCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrUnknownNeighborCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrUnknownNeighborCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrSecCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrSecCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrFcsCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrFcsCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrOtherCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrOtherCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsActiveTimestamp>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsActiveTimestamp>(), //
        make_unique<ReadThreadNetworkDiagnosticsPendingTimestamp>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsPendingTimestamp>(), //
        make_unique<ReadThreadNetworkDiagnosticsDelay>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsDelay>(), //
        make_unique<ReadThreadNetworkDiagnosticsSecurityPolicy>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsSecurityPolicy>(), //
        make_unique<ReadThreadNetworkDiagnosticsChannelMask>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsChannelMask>(), //
        make_unique<ReadThreadNetworkDiagnosticsOperationalDatasetComponents>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsOperationalDatasetComponents>(), //
        make_unique<ReadThreadNetworkDiagnosticsActiveNetworkFaultsList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsActiveNetworkFaultsList>(), //
        make_unique<ReadThreadNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<ReadThreadNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<ReadThreadNetworkDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsAttributeList>(), //
        make_unique<ReadThreadNetworkDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsFeatureMap>(), //
        make_unique<ReadThreadNetworkDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterWiFiNetworkDiagnostics(Commands & commands)
{
    using namespace chip::app::Clusters::WiFiNetworkDiagnostics;

    const char * clusterName = "WiFiNetworkDiagnostics";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<WiFiNetworkDiagnosticsResetCounts>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadWiFiNetworkDiagnosticsBssid>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsBssid>(), //
        make_unique<ReadWiFiNetworkDiagnosticsSecurityType>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsSecurityType>(), //
        make_unique<ReadWiFiNetworkDiagnosticsWiFiVersion>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsWiFiVersion>(), //
        make_unique<ReadWiFiNetworkDiagnosticsChannelNumber>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsChannelNumber>(), //
        make_unique<ReadWiFiNetworkDiagnosticsRssi>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsRssi>(), //
        make_unique<ReadWiFiNetworkDiagnosticsBeaconLostCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsBeaconLostCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsBeaconRxCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsBeaconRxCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsPacketMulticastRxCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastRxCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsPacketMulticastTxCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastTxCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsPacketUnicastRxCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastRxCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsPacketUnicastTxCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastTxCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsCurrentMaxRate>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsCurrentMaxRate>(), //
        make_unique<ReadWiFiNetworkDiagnosticsOverrunCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsOverrunCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<ReadWiFiNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<ReadWiFiNetworkDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsAttributeList>(), //
        make_unique<ReadWiFiNetworkDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsFeatureMap>(), //
        make_unique<ReadWiFiNetworkDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterEthernetNetworkDiagnostics(Commands & commands)
{
    using namespace chip::app::Clusters::EthernetNetworkDiagnostics;

    const char * clusterName = "EthernetNetworkDiagnostics";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<EthernetNetworkDiagnosticsResetCounts>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadEthernetNetworkDiagnosticsPHYRate>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsPHYRate>(), //
        make_unique<ReadEthernetNetworkDiagnosticsFullDuplex>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsFullDuplex>(), //
        make_unique<ReadEthernetNetworkDiagnosticsPacketRxCount>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsPacketRxCount>(), //
        make_unique<ReadEthernetNetworkDiagnosticsPacketTxCount>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsPacketTxCount>(), //
        make_unique<ReadEthernetNetworkDiagnosticsTxErrCount>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsTxErrCount>(), //
        make_unique<ReadEthernetNetworkDiagnosticsCollisionCount>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsCollisionCount>(), //
        make_unique<ReadEthernetNetworkDiagnosticsOverrunCount>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsOverrunCount>(), //
        make_unique<ReadEthernetNetworkDiagnosticsCarrierDetect>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsCarrierDetect>(), //
        make_unique<ReadEthernetNetworkDiagnosticsTimeSinceReset>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsTimeSinceReset>(), //
        make_unique<ReadEthernetNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<ReadEthernetNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<ReadEthernetNetworkDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsAttributeList>(), //
        make_unique<ReadEthernetNetworkDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsFeatureMap>(), //
        make_unique<ReadEthernetNetworkDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBridgedDeviceBasic(Commands & commands)
{
    using namespace chip::app::Clusters::BridgedDeviceBasic;

    const char * clusterName = "BridgedDeviceBasic";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBridgedDeviceBasicVendorName>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBridgedDeviceBasicVendorName>(), //
        make_unique<ReadBridgedDeviceBasicVendorID>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicVendorID>(), //
        make_unique<ReadBridgedDeviceBasicProductName>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicProductName>(), //
        make_unique<ReadBridgedDeviceBasicNodeLabel>(), //
        make_unique<WriteBridgedDeviceBasicNodeLabel>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicNodeLabel>(), //
        make_unique<ReadBridgedDeviceBasicHardwareVersion>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicHardwareVersion>(), //
        make_unique<ReadBridgedDeviceBasicHardwareVersionString>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicHardwareVersionString>(), //
        make_unique<ReadBridgedDeviceBasicSoftwareVersion>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicSoftwareVersion>(), //
        make_unique<ReadBridgedDeviceBasicSoftwareVersionString>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicSoftwareVersionString>(), //
        make_unique<ReadBridgedDeviceBasicManufacturingDate>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicManufacturingDate>(), //
        make_unique<ReadBridgedDeviceBasicPartNumber>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicPartNumber>(), //
        make_unique<ReadBridgedDeviceBasicProductURL>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicProductURL>(), //
        make_unique<ReadBridgedDeviceBasicProductLabel>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicProductLabel>(), //
        make_unique<ReadBridgedDeviceBasicSerialNumber>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicSerialNumber>(), //
        make_unique<ReadBridgedDeviceBasicReachable>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicReachable>(), //
        make_unique<ReadBridgedDeviceBasicUniqueID>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicUniqueID>(), //
        make_unique<ReadBridgedDeviceBasicGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicGeneratedCommandList>(), //
        make_unique<ReadBridgedDeviceBasicAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicAcceptedCommandList>(), //
        make_unique<ReadBridgedDeviceBasicAttributeList>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicAttributeList>(), //
        make_unique<ReadBridgedDeviceBasicFeatureMap>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicFeatureMap>(), //
        make_unique<ReadBridgedDeviceBasicClusterRevision>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterSwitch(Commands & commands)
{
    using namespace chip::app::Clusters::Switch;

    const char * clusterName = "Switch";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadSwitchNumberOfPositions>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeSwitchNumberOfPositions>(), //
        make_unique<ReadSwitchCurrentPosition>(), //
        make_unique<SubscribeAttributeSwitchCurrentPosition>(), //
        make_unique<ReadSwitchMultiPressMax>(), //
        make_unique<SubscribeAttributeSwitchMultiPressMax>(), //
        make_unique<ReadSwitchGeneratedCommandList>(), //
        make_unique<SubscribeAttributeSwitchGeneratedCommandList>(), //
        make_unique<ReadSwitchAcceptedCommandList>(), //
        make_unique<SubscribeAttributeSwitchAcceptedCommandList>(), //
        make_unique<ReadSwitchAttributeList>(), //
        make_unique<SubscribeAttributeSwitchAttributeList>(), //
        make_unique<ReadSwitchFeatureMap>(), //
        make_unique<SubscribeAttributeSwitchFeatureMap>(), //
        make_unique<ReadSwitchClusterRevision>(), //
        make_unique<SubscribeAttributeSwitchClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterAdministratorCommissioning(Commands & commands)
{
    using namespace chip::app::Clusters::AdministratorCommissioning;

    const char * clusterName = "AdministratorCommissioning";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<AdministratorCommissioningOpenCommissioningWindow>(), //
        make_unique<AdministratorCommissioningOpenBasicCommissioningWindow>(), //
        make_unique<AdministratorCommissioningRevokeCommissioning>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadAdministratorCommissioningWindowStatus>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeAdministratorCommissioningWindowStatus>(), //
        make_unique<ReadAdministratorCommissioningAdminFabricIndex>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningAdminFabricIndex>(), //
        make_unique<ReadAdministratorCommissioningAdminVendorId>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningAdminVendorId>(), //
        make_unique<ReadAdministratorCommissioningGeneratedCommandList>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningGeneratedCommandList>(), //
        make_unique<ReadAdministratorCommissioningAcceptedCommandList>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningAcceptedCommandList>(), //
        make_unique<ReadAdministratorCommissioningAttributeList>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningAttributeList>(), //
        make_unique<ReadAdministratorCommissioningFeatureMap>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningFeatureMap>(), //
        make_unique<ReadAdministratorCommissioningClusterRevision>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOperationalCredentials(Commands & commands)
{
    using namespace chip::app::Clusters::OperationalCredentials;

    const char * clusterName = "OperationalCredentials";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<OperationalCredentialsAttestationRequest>(), //
        make_unique<OperationalCredentialsCertificateChainRequest>(), //
        make_unique<OperationalCredentialsCSRRequest>(), //
        make_unique<OperationalCredentialsAddNOC>(), //
        make_unique<OperationalCredentialsUpdateNOC>(), //
        make_unique<OperationalCredentialsUpdateFabricLabel>(), //
        make_unique<OperationalCredentialsRemoveFabric>(), //
        make_unique<OperationalCredentialsAddTrustedRootCertificate>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOperationalCredentialsNOCs>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOperationalCredentialsNOCs>(), //
        make_unique<ReadOperationalCredentialsFabrics>(), //
        make_unique<SubscribeAttributeOperationalCredentialsFabrics>(), //
        make_unique<ReadOperationalCredentialsSupportedFabrics>(), //
        make_unique<SubscribeAttributeOperationalCredentialsSupportedFabrics>(), //
        make_unique<ReadOperationalCredentialsCommissionedFabrics>(), //
        make_unique<SubscribeAttributeOperationalCredentialsCommissionedFabrics>(), //
        make_unique<ReadOperationalCredentialsTrustedRootCertificates>(), //
        make_unique<SubscribeAttributeOperationalCredentialsTrustedRootCertificates>(), //
        make_unique<ReadOperationalCredentialsCurrentFabricIndex>(), //
        make_unique<SubscribeAttributeOperationalCredentialsCurrentFabricIndex>(), //
        make_unique<ReadOperationalCredentialsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOperationalCredentialsGeneratedCommandList>(), //
        make_unique<ReadOperationalCredentialsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOperationalCredentialsAcceptedCommandList>(), //
        make_unique<ReadOperationalCredentialsAttributeList>(), //
        make_unique<SubscribeAttributeOperationalCredentialsAttributeList>(), //
        make_unique<ReadOperationalCredentialsFeatureMap>(), //
        make_unique<SubscribeAttributeOperationalCredentialsFeatureMap>(), //
        make_unique<ReadOperationalCredentialsClusterRevision>(), //
        make_unique<SubscribeAttributeOperationalCredentialsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterGroupKeyManagement(Commands & commands)
{
    using namespace chip::app::Clusters::GroupKeyManagement;

    const char * clusterName = "GroupKeyManagement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<GroupKeyManagementKeySetWrite>(), //
        make_unique<GroupKeyManagementKeySetRead>(), //
        make_unique<GroupKeyManagementKeySetRemove>(), //
        make_unique<GroupKeyManagementKeySetReadAllIndices>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadGroupKeyManagementGroupKeyMap>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteGroupKeyManagementGroupKeyMap>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeGroupKeyManagementGroupKeyMap>(), //
        make_unique<ReadGroupKeyManagementGroupTable>(), //
        make_unique<SubscribeAttributeGroupKeyManagementGroupTable>(), //
        make_unique<ReadGroupKeyManagementMaxGroupsPerFabric>(), //
        make_unique<SubscribeAttributeGroupKeyManagementMaxGroupsPerFabric>(), //
        make_unique<ReadGroupKeyManagementMaxGroupKeysPerFabric>(), //
        make_unique<SubscribeAttributeGroupKeyManagementMaxGroupKeysPerFabric>(), //
        make_unique<ReadGroupKeyManagementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeGroupKeyManagementGeneratedCommandList>(), //
        make_unique<ReadGroupKeyManagementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeGroupKeyManagementAcceptedCommandList>(), //
        make_unique<ReadGroupKeyManagementAttributeList>(), //
        make_unique<SubscribeAttributeGroupKeyManagementAttributeList>(), //
        make_unique<ReadGroupKeyManagementFeatureMap>(), //
        make_unique<SubscribeAttributeGroupKeyManagementFeatureMap>(), //
        make_unique<ReadGroupKeyManagementClusterRevision>(), //
        make_unique<SubscribeAttributeGroupKeyManagementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterFixedLabel(Commands & commands)
{
    using namespace chip::app::Clusters::FixedLabel;

    const char * clusterName = "FixedLabel";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadFixedLabelLabelList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeFixedLabelLabelList>(), //
        make_unique<ReadFixedLabelGeneratedCommandList>(), //
        make_unique<SubscribeAttributeFixedLabelGeneratedCommandList>(), //
        make_unique<ReadFixedLabelAcceptedCommandList>(), //
        make_unique<SubscribeAttributeFixedLabelAcceptedCommandList>(), //
        make_unique<ReadFixedLabelAttributeList>(), //
        make_unique<SubscribeAttributeFixedLabelAttributeList>(), //
        make_unique<ReadFixedLabelFeatureMap>(), //
        make_unique<SubscribeAttributeFixedLabelFeatureMap>(), //
        make_unique<ReadFixedLabelClusterRevision>(), //
        make_unique<SubscribeAttributeFixedLabelClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterUserLabel(Commands & commands)
{
    using namespace chip::app::Clusters::UserLabel;

    const char * clusterName = "UserLabel";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadUserLabelLabelList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteUserLabelLabelList>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeUserLabelLabelList>(), //
        make_unique<ReadUserLabelGeneratedCommandList>(), //
        make_unique<SubscribeAttributeUserLabelGeneratedCommandList>(), //
        make_unique<ReadUserLabelAcceptedCommandList>(), //
        make_unique<SubscribeAttributeUserLabelAcceptedCommandList>(), //
        make_unique<ReadUserLabelAttributeList>(), //
        make_unique<SubscribeAttributeUserLabelAttributeList>(), //
        make_unique<ReadUserLabelFeatureMap>(), //
        make_unique<SubscribeAttributeUserLabelFeatureMap>(), //
        make_unique<ReadUserLabelClusterRevision>(), //
        make_unique<SubscribeAttributeUserLabelClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBooleanState(Commands & commands)
{
    using namespace chip::app::Clusters::BooleanState;

    const char * clusterName = "BooleanState";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBooleanStateStateValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBooleanStateStateValue>(), //
        make_unique<ReadBooleanStateGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBooleanStateGeneratedCommandList>(), //
        make_unique<ReadBooleanStateAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBooleanStateAcceptedCommandList>(), //
        make_unique<ReadBooleanStateAttributeList>(), //
        make_unique<SubscribeAttributeBooleanStateAttributeList>(), //
        make_unique<ReadBooleanStateFeatureMap>(), //
        make_unique<SubscribeAttributeBooleanStateFeatureMap>(), //
        make_unique<ReadBooleanStateClusterRevision>(), //
        make_unique<SubscribeAttributeBooleanStateClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterModeSelect(Commands & commands)
{
    using namespace chip::app::Clusters::ModeSelect;

    const char * clusterName = "ModeSelect";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ModeSelectChangeToMode>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadModeSelectDescription>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeModeSelectDescription>(), //
        make_unique<ReadModeSelectStandardNamespace>(), //
        make_unique<SubscribeAttributeModeSelectStandardNamespace>(), //
        make_unique<ReadModeSelectSupportedModes>(), //
        make_unique<SubscribeAttributeModeSelectSupportedModes>(), //
        make_unique<ReadModeSelectCurrentMode>(), //
        make_unique<SubscribeAttributeModeSelectCurrentMode>(), //
        make_unique<ReadModeSelectStartUpMode>(), //
        make_unique<WriteModeSelectStartUpMode>(), //
        make_unique<SubscribeAttributeModeSelectStartUpMode>(), //
        make_unique<ReadModeSelectOnMode>(), //
        make_unique<WriteModeSelectOnMode>(), //
        make_unique<SubscribeAttributeModeSelectOnMode>(), //
        make_unique<ReadModeSelectGeneratedCommandList>(), //
        make_unique<SubscribeAttributeModeSelectGeneratedCommandList>(), //
        make_unique<ReadModeSelectAcceptedCommandList>(), //
        make_unique<SubscribeAttributeModeSelectAcceptedCommandList>(), //
        make_unique<ReadModeSelectAttributeList>(), //
        make_unique<SubscribeAttributeModeSelectAttributeList>(), //
        make_unique<ReadModeSelectFeatureMap>(), //
        make_unique<SubscribeAttributeModeSelectFeatureMap>(), //
        make_unique<ReadModeSelectClusterRevision>(), //
        make_unique<SubscribeAttributeModeSelectClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterDoorLock(Commands & commands)
{
    using namespace chip::app::Clusters::DoorLock;

    const char * clusterName = "DoorLock";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<DoorLockLockDoor>(), //
        make_unique<DoorLockUnlockDoor>(), //
        make_unique<DoorLockUnlockWithTimeout>(), //
        make_unique<DoorLockSetWeekDaySchedule>(), //
        make_unique<DoorLockGetWeekDaySchedule>(), //
        make_unique<DoorLockClearWeekDaySchedule>(), //
        make_unique<DoorLockSetYearDaySchedule>(), //
        make_unique<DoorLockGetYearDaySchedule>(), //
        make_unique<DoorLockClearYearDaySchedule>(), //
        make_unique<DoorLockSetHolidaySchedule>(), //
        make_unique<DoorLockGetHolidaySchedule>(), //
        make_unique<DoorLockClearHolidaySchedule>(), //
        make_unique<DoorLockSetUser>(), //
        make_unique<DoorLockGetUser>(), //
        make_unique<DoorLockClearUser>(), //
        make_unique<DoorLockSetCredential>(), //
        make_unique<DoorLockGetCredentialStatus>(), //
        make_unique<DoorLockClearCredential>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadDoorLockLockState>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeDoorLockLockState>(), //
        make_unique<ReadDoorLockLockType>(), //
        make_unique<SubscribeAttributeDoorLockLockType>(), //
        make_unique<ReadDoorLockActuatorEnabled>(), //
        make_unique<SubscribeAttributeDoorLockActuatorEnabled>(), //
        make_unique<ReadDoorLockDoorState>(), //
        make_unique<SubscribeAttributeDoorLockDoorState>(), //
        make_unique<ReadDoorLockDoorOpenEvents>(), //
        make_unique<WriteDoorLockDoorOpenEvents>(), //
        make_unique<SubscribeAttributeDoorLockDoorOpenEvents>(), //
        make_unique<ReadDoorLockDoorClosedEvents>(), //
        make_unique<WriteDoorLockDoorClosedEvents>(), //
        make_unique<SubscribeAttributeDoorLockDoorClosedEvents>(), //
        make_unique<ReadDoorLockOpenPeriod>(), //
        make_unique<WriteDoorLockOpenPeriod>(), //
        make_unique<SubscribeAttributeDoorLockOpenPeriod>(), //
        make_unique<ReadDoorLockNumberOfTotalUsersSupported>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfTotalUsersSupported>(), //
        make_unique<ReadDoorLockNumberOfPINUsersSupported>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfPINUsersSupported>(), //
        make_unique<ReadDoorLockNumberOfRFIDUsersSupported>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfRFIDUsersSupported>(), //
        make_unique<ReadDoorLockNumberOfWeekDaySchedulesSupportedPerUser>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfWeekDaySchedulesSupportedPerUser>(), //
        make_unique<ReadDoorLockNumberOfYearDaySchedulesSupportedPerUser>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfYearDaySchedulesSupportedPerUser>(), //
        make_unique<ReadDoorLockNumberOfHolidaySchedulesSupported>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfHolidaySchedulesSupported>(), //
        make_unique<ReadDoorLockMaxPINCodeLength>(), //
        make_unique<SubscribeAttributeDoorLockMaxPINCodeLength>(), //
        make_unique<ReadDoorLockMinPINCodeLength>(), //
        make_unique<SubscribeAttributeDoorLockMinPINCodeLength>(), //
        make_unique<ReadDoorLockMaxRFIDCodeLength>(), //
        make_unique<SubscribeAttributeDoorLockMaxRFIDCodeLength>(), //
        make_unique<ReadDoorLockMinRFIDCodeLength>(), //
        make_unique<SubscribeAttributeDoorLockMinRFIDCodeLength>(), //
        make_unique<ReadDoorLockCredentialRulesSupport>(), //
        make_unique<SubscribeAttributeDoorLockCredentialRulesSupport>(), //
        make_unique<ReadDoorLockNumberOfCredentialsSupportedPerUser>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfCredentialsSupportedPerUser>(), //
        make_unique<ReadDoorLockLanguage>(), //
        make_unique<WriteDoorLockLanguage>(), //
        make_unique<SubscribeAttributeDoorLockLanguage>(), //
        make_unique<ReadDoorLockLEDSettings>(), //
        make_unique<WriteDoorLockLEDSettings>(), //
        make_unique<SubscribeAttributeDoorLockLEDSettings>(), //
        make_unique<ReadDoorLockAutoRelockTime>(), //
        make_unique<WriteDoorLockAutoRelockTime>(), //
        make_unique<SubscribeAttributeDoorLockAutoRelockTime>(), //
        make_unique<ReadDoorLockSoundVolume>(), //
        make_unique<WriteDoorLockSoundVolume>(), //
        make_unique<SubscribeAttributeDoorLockSoundVolume>(), //
        make_unique<ReadDoorLockOperatingMode>(), //
        make_unique<WriteDoorLockOperatingMode>(), //
        make_unique<SubscribeAttributeDoorLockOperatingMode>(), //
        make_unique<ReadDoorLockSupportedOperatingModes>(), //
        make_unique<SubscribeAttributeDoorLockSupportedOperatingModes>(), //
        make_unique<ReadDoorLockDefaultConfigurationRegister>(), //
        make_unique<SubscribeAttributeDoorLockDefaultConfigurationRegister>(), //
        make_unique<ReadDoorLockEnableLocalProgramming>(), //
        make_unique<WriteDoorLockEnableLocalProgramming>(), //
        make_unique<SubscribeAttributeDoorLockEnableLocalProgramming>(), //
        make_unique<ReadDoorLockEnableOneTouchLocking>(), //
        make_unique<WriteDoorLockEnableOneTouchLocking>(), //
        make_unique<SubscribeAttributeDoorLockEnableOneTouchLocking>(), //
        make_unique<ReadDoorLockEnableInsideStatusLED>(), //
        make_unique<WriteDoorLockEnableInsideStatusLED>(), //
        make_unique<SubscribeAttributeDoorLockEnableInsideStatusLED>(), //
        make_unique<ReadDoorLockEnablePrivacyModeButton>(), //
        make_unique<WriteDoorLockEnablePrivacyModeButton>(), //
        make_unique<SubscribeAttributeDoorLockEnablePrivacyModeButton>(), //
        make_unique<ReadDoorLockLocalProgrammingFeatures>(), //
        make_unique<WriteDoorLockLocalProgrammingFeatures>(), //
        make_unique<SubscribeAttributeDoorLockLocalProgrammingFeatures>(), //
        make_unique<ReadDoorLockWrongCodeEntryLimit>(), //
        make_unique<WriteDoorLockWrongCodeEntryLimit>(), //
        make_unique<SubscribeAttributeDoorLockWrongCodeEntryLimit>(), //
        make_unique<ReadDoorLockUserCodeTemporaryDisableTime>(), //
        make_unique<WriteDoorLockUserCodeTemporaryDisableTime>(), //
        make_unique<SubscribeAttributeDoorLockUserCodeTemporaryDisableTime>(), //
        make_unique<ReadDoorLockSendPINOverTheAir>(), //
        make_unique<WriteDoorLockSendPINOverTheAir>(), //
        make_unique<SubscribeAttributeDoorLockSendPINOverTheAir>(), //
        make_unique<ReadDoorLockRequirePINforRemoteOperation>(), //
        make_unique<WriteDoorLockRequirePINforRemoteOperation>(), //
        make_unique<SubscribeAttributeDoorLockRequirePINforRemoteOperation>(), //
        make_unique<ReadDoorLockExpiringUserTimeout>(), //
        make_unique<WriteDoorLockExpiringUserTimeout>(), //
        make_unique<SubscribeAttributeDoorLockExpiringUserTimeout>(), //
        make_unique<ReadDoorLockGeneratedCommandList>(), //
        make_unique<SubscribeAttributeDoorLockGeneratedCommandList>(), //
        make_unique<ReadDoorLockAcceptedCommandList>(), //
        make_unique<SubscribeAttributeDoorLockAcceptedCommandList>(), //
        make_unique<ReadDoorLockAttributeList>(), //
        make_unique<SubscribeAttributeDoorLockAttributeList>(), //
        make_unique<ReadDoorLockFeatureMap>(), //
        make_unique<SubscribeAttributeDoorLockFeatureMap>(), //
        make_unique<ReadDoorLockClusterRevision>(), //
        make_unique<SubscribeAttributeDoorLockClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterWindowCovering(Commands & commands)
{
    using namespace chip::app::Clusters::WindowCovering;

    const char * clusterName = "WindowCovering";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<WindowCoveringUpOrOpen>(), //
        make_unique<WindowCoveringDownOrClose>(), //
        make_unique<WindowCoveringStopMotion>(), //
        make_unique<WindowCoveringGoToLiftValue>(), //
        make_unique<WindowCoveringGoToLiftPercentage>(), //
        make_unique<WindowCoveringGoToTiltValue>(), //
        make_unique<WindowCoveringGoToTiltPercentage>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadWindowCoveringType>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeWindowCoveringType>(), //
        make_unique<ReadWindowCoveringPhysicalClosedLimitLift>(), //
        make_unique<SubscribeAttributeWindowCoveringPhysicalClosedLimitLift>(), //
        make_unique<ReadWindowCoveringPhysicalClosedLimitTilt>(), //
        make_unique<SubscribeAttributeWindowCoveringPhysicalClosedLimitTilt>(), //
        make_unique<ReadWindowCoveringCurrentPositionLift>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionLift>(), //
        make_unique<ReadWindowCoveringCurrentPositionTilt>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionTilt>(), //
        make_unique<ReadWindowCoveringNumberOfActuationsLift>(), //
        make_unique<SubscribeAttributeWindowCoveringNumberOfActuationsLift>(), //
        make_unique<ReadWindowCoveringNumberOfActuationsTilt>(), //
        make_unique<SubscribeAttributeWindowCoveringNumberOfActuationsTilt>(), //
        make_unique<ReadWindowCoveringConfigStatus>(), //
        make_unique<SubscribeAttributeWindowCoveringConfigStatus>(), //
        make_unique<ReadWindowCoveringCurrentPositionLiftPercentage>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionLiftPercentage>(), //
        make_unique<ReadWindowCoveringCurrentPositionTiltPercentage>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionTiltPercentage>(), //
        make_unique<ReadWindowCoveringOperationalStatus>(), //
        make_unique<SubscribeAttributeWindowCoveringOperationalStatus>(), //
        make_unique<ReadWindowCoveringTargetPositionLiftPercent100ths>(), //
        make_unique<SubscribeAttributeWindowCoveringTargetPositionLiftPercent100ths>(), //
        make_unique<ReadWindowCoveringTargetPositionTiltPercent100ths>(), //
        make_unique<SubscribeAttributeWindowCoveringTargetPositionTiltPercent100ths>(), //
        make_unique<ReadWindowCoveringEndProductType>(), //
        make_unique<SubscribeAttributeWindowCoveringEndProductType>(), //
        make_unique<ReadWindowCoveringCurrentPositionLiftPercent100ths>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionLiftPercent100ths>(), //
        make_unique<ReadWindowCoveringCurrentPositionTiltPercent100ths>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionTiltPercent100ths>(), //
        make_unique<ReadWindowCoveringInstalledOpenLimitLift>(), //
        make_unique<SubscribeAttributeWindowCoveringInstalledOpenLimitLift>(), //
        make_unique<ReadWindowCoveringInstalledClosedLimitLift>(), //
        make_unique<SubscribeAttributeWindowCoveringInstalledClosedLimitLift>(), //
        make_unique<ReadWindowCoveringInstalledOpenLimitTilt>(), //
        make_unique<SubscribeAttributeWindowCoveringInstalledOpenLimitTilt>(), //
        make_unique<ReadWindowCoveringInstalledClosedLimitTilt>(), //
        make_unique<SubscribeAttributeWindowCoveringInstalledClosedLimitTilt>(), //
        make_unique<ReadWindowCoveringMode>(), //
        make_unique<WriteWindowCoveringMode>(), //
        make_unique<SubscribeAttributeWindowCoveringMode>(), //
        make_unique<ReadWindowCoveringSafetyStatus>(), //
        make_unique<SubscribeAttributeWindowCoveringSafetyStatus>(), //
        make_unique<ReadWindowCoveringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeWindowCoveringGeneratedCommandList>(), //
        make_unique<ReadWindowCoveringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeWindowCoveringAcceptedCommandList>(), //
        make_unique<ReadWindowCoveringAttributeList>(), //
        make_unique<SubscribeAttributeWindowCoveringAttributeList>(), //
        make_unique<ReadWindowCoveringFeatureMap>(), //
        make_unique<SubscribeAttributeWindowCoveringFeatureMap>(), //
        make_unique<ReadWindowCoveringClusterRevision>(), //
        make_unique<SubscribeAttributeWindowCoveringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBarrierControl(Commands & commands)
{
    using namespace chip::app::Clusters::BarrierControl;

    const char * clusterName = "BarrierControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<BarrierControlBarrierControlGoToPercent>(), //
        make_unique<BarrierControlBarrierControlStop>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBarrierControlBarrierMovingState>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBarrierControlBarrierMovingState>(), //
        make_unique<ReadBarrierControlBarrierSafetyStatus>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierSafetyStatus>(), //
        make_unique<ReadBarrierControlBarrierCapabilities>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierCapabilities>(), //
        make_unique<ReadBarrierControlBarrierOpenEvents>(), //
        make_unique<WriteBarrierControlBarrierOpenEvents>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierOpenEvents>(), //
        make_unique<ReadBarrierControlBarrierCloseEvents>(), //
        make_unique<WriteBarrierControlBarrierCloseEvents>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierCloseEvents>(), //
        make_unique<ReadBarrierControlBarrierCommandOpenEvents>(), //
        make_unique<WriteBarrierControlBarrierCommandOpenEvents>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierCommandOpenEvents>(), //
        make_unique<ReadBarrierControlBarrierCommandCloseEvents>(), //
        make_unique<WriteBarrierControlBarrierCommandCloseEvents>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierCommandCloseEvents>(), //
        make_unique<ReadBarrierControlBarrierOpenPeriod>(), //
        make_unique<WriteBarrierControlBarrierOpenPeriod>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierOpenPeriod>(), //
        make_unique<ReadBarrierControlBarrierClosePeriod>(), //
        make_unique<WriteBarrierControlBarrierClosePeriod>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierClosePeriod>(), //
        make_unique<ReadBarrierControlBarrierPosition>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierPosition>(), //
        make_unique<ReadBarrierControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBarrierControlGeneratedCommandList>(), //
        make_unique<ReadBarrierControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBarrierControlAcceptedCommandList>(), //
        make_unique<ReadBarrierControlAttributeList>(), //
        make_unique<SubscribeAttributeBarrierControlAttributeList>(), //
        make_unique<ReadBarrierControlFeatureMap>(), //
        make_unique<SubscribeAttributeBarrierControlFeatureMap>(), //
        make_unique<ReadBarrierControlClusterRevision>(), //
        make_unique<SubscribeAttributeBarrierControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterPumpConfigurationAndControl(Commands & commands)
{
    using namespace chip::app::Clusters::PumpConfigurationAndControl;

    const char * clusterName = "PumpConfigurationAndControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadPumpConfigurationAndControlMaxPressure>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxPressure>(), //
        make_unique<ReadPumpConfigurationAndControlMaxSpeed>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxSpeed>(), //
        make_unique<ReadPumpConfigurationAndControlMaxFlow>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxFlow>(), //
        make_unique<ReadPumpConfigurationAndControlMinConstPressure>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMinConstPressure>(), //
        make_unique<ReadPumpConfigurationAndControlMaxConstPressure>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxConstPressure>(), //
        make_unique<ReadPumpConfigurationAndControlMinCompPressure>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMinCompPressure>(), //
        make_unique<ReadPumpConfigurationAndControlMaxCompPressure>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxCompPressure>(), //
        make_unique<ReadPumpConfigurationAndControlMinConstSpeed>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMinConstSpeed>(), //
        make_unique<ReadPumpConfigurationAndControlMaxConstSpeed>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxConstSpeed>(), //
        make_unique<ReadPumpConfigurationAndControlMinConstFlow>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMinConstFlow>(), //
        make_unique<ReadPumpConfigurationAndControlMaxConstFlow>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxConstFlow>(), //
        make_unique<ReadPumpConfigurationAndControlMinConstTemp>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMinConstTemp>(), //
        make_unique<ReadPumpConfigurationAndControlMaxConstTemp>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxConstTemp>(), //
        make_unique<ReadPumpConfigurationAndControlPumpStatus>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlPumpStatus>(), //
        make_unique<ReadPumpConfigurationAndControlEffectiveOperationMode>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlEffectiveOperationMode>(), //
        make_unique<ReadPumpConfigurationAndControlEffectiveControlMode>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlEffectiveControlMode>(), //
        make_unique<ReadPumpConfigurationAndControlCapacity>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlCapacity>(), //
        make_unique<ReadPumpConfigurationAndControlSpeed>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlSpeed>(), //
        make_unique<ReadPumpConfigurationAndControlLifetimeRunningHours>(), //
        make_unique<WritePumpConfigurationAndControlLifetimeRunningHours>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlLifetimeRunningHours>(), //
        make_unique<ReadPumpConfigurationAndControlPower>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlPower>(), //
        make_unique<ReadPumpConfigurationAndControlLifetimeEnergyConsumed>(), //
        make_unique<WritePumpConfigurationAndControlLifetimeEnergyConsumed>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlLifetimeEnergyConsumed>(), //
        make_unique<ReadPumpConfigurationAndControlOperationMode>(), //
        make_unique<WritePumpConfigurationAndControlOperationMode>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlOperationMode>(), //
        make_unique<ReadPumpConfigurationAndControlControlMode>(), //
        make_unique<WritePumpConfigurationAndControlControlMode>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlControlMode>(), //
        make_unique<ReadPumpConfigurationAndControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlGeneratedCommandList>(), //
        make_unique<ReadPumpConfigurationAndControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlAcceptedCommandList>(), //
        make_unique<ReadPumpConfigurationAndControlAttributeList>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlAttributeList>(), //
        make_unique<ReadPumpConfigurationAndControlFeatureMap>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlFeatureMap>(), //
        make_unique<ReadPumpConfigurationAndControlClusterRevision>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterThermostat(Commands & commands)
{
    using namespace chip::app::Clusters::Thermostat;

    const char * clusterName = "Thermostat";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ThermostatSetpointRaiseLower>(), //
        make_unique<ThermostatSetWeeklySchedule>(), //
        make_unique<ThermostatGetWeeklySchedule>(), //
        make_unique<ThermostatClearWeeklySchedule>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadThermostatLocalTemperature>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeThermostatLocalTemperature>(), //
        make_unique<ReadThermostatOutdoorTemperature>(), //
        make_unique<SubscribeAttributeThermostatOutdoorTemperature>(), //
        make_unique<ReadThermostatOccupancy>(), //
        make_unique<SubscribeAttributeThermostatOccupancy>(), //
        make_unique<ReadThermostatAbsMinHeatSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatAbsMinHeatSetpointLimit>(), //
        make_unique<ReadThermostatAbsMaxHeatSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatAbsMaxHeatSetpointLimit>(), //
        make_unique<ReadThermostatAbsMinCoolSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatAbsMinCoolSetpointLimit>(), //
        make_unique<ReadThermostatAbsMaxCoolSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatAbsMaxCoolSetpointLimit>(), //
        make_unique<ReadThermostatPICoolingDemand>(), //
        make_unique<SubscribeAttributeThermostatPICoolingDemand>(), //
        make_unique<ReadThermostatPIHeatingDemand>(), //
        make_unique<SubscribeAttributeThermostatPIHeatingDemand>(), //
        make_unique<ReadThermostatHVACSystemTypeConfiguration>(), //
        make_unique<WriteThermostatHVACSystemTypeConfiguration>(), //
        make_unique<SubscribeAttributeThermostatHVACSystemTypeConfiguration>(), //
        make_unique<ReadThermostatLocalTemperatureCalibration>(), //
        make_unique<WriteThermostatLocalTemperatureCalibration>(), //
        make_unique<SubscribeAttributeThermostatLocalTemperatureCalibration>(), //
        make_unique<ReadThermostatOccupiedCoolingSetpoint>(), //
        make_unique<WriteThermostatOccupiedCoolingSetpoint>(), //
        make_unique<SubscribeAttributeThermostatOccupiedCoolingSetpoint>(), //
        make_unique<ReadThermostatOccupiedHeatingSetpoint>(), //
        make_unique<WriteThermostatOccupiedHeatingSetpoint>(), //
        make_unique<SubscribeAttributeThermostatOccupiedHeatingSetpoint>(), //
        make_unique<ReadThermostatUnoccupiedCoolingSetpoint>(), //
        make_unique<WriteThermostatUnoccupiedCoolingSetpoint>(), //
        make_unique<SubscribeAttributeThermostatUnoccupiedCoolingSetpoint>(), //
        make_unique<ReadThermostatUnoccupiedHeatingSetpoint>(), //
        make_unique<WriteThermostatUnoccupiedHeatingSetpoint>(), //
        make_unique<SubscribeAttributeThermostatUnoccupiedHeatingSetpoint>(), //
        make_unique<ReadThermostatMinHeatSetpointLimit>(), //
        make_unique<WriteThermostatMinHeatSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatMinHeatSetpointLimit>(), //
        make_unique<ReadThermostatMaxHeatSetpointLimit>(), //
        make_unique<WriteThermostatMaxHeatSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatMaxHeatSetpointLimit>(), //
        make_unique<ReadThermostatMinCoolSetpointLimit>(), //
        make_unique<WriteThermostatMinCoolSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatMinCoolSetpointLimit>(), //
        make_unique<ReadThermostatMaxCoolSetpointLimit>(), //
        make_unique<WriteThermostatMaxCoolSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatMaxCoolSetpointLimit>(), //
        make_unique<ReadThermostatMinSetpointDeadBand>(), //
        make_unique<WriteThermostatMinSetpointDeadBand>(), //
        make_unique<SubscribeAttributeThermostatMinSetpointDeadBand>(), //
        make_unique<ReadThermostatRemoteSensing>(), //
        make_unique<WriteThermostatRemoteSensing>(), //
        make_unique<SubscribeAttributeThermostatRemoteSensing>(), //
        make_unique<ReadThermostatControlSequenceOfOperation>(), //
        make_unique<WriteThermostatControlSequenceOfOperation>(), //
        make_unique<SubscribeAttributeThermostatControlSequenceOfOperation>(), //
        make_unique<ReadThermostatSystemMode>(), //
        make_unique<WriteThermostatSystemMode>(), //
        make_unique<SubscribeAttributeThermostatSystemMode>(), //
        make_unique<ReadThermostatThermostatRunningMode>(), //
        make_unique<SubscribeAttributeThermostatThermostatRunningMode>(), //
        make_unique<ReadThermostatStartOfWeek>(), //
        make_unique<SubscribeAttributeThermostatStartOfWeek>(), //
        make_unique<ReadThermostatNumberOfWeeklyTransitions>(), //
        make_unique<SubscribeAttributeThermostatNumberOfWeeklyTransitions>(), //
        make_unique<ReadThermostatNumberOfDailyTransitions>(), //
        make_unique<SubscribeAttributeThermostatNumberOfDailyTransitions>(), //
        make_unique<ReadThermostatTemperatureSetpointHold>(), //
        make_unique<WriteThermostatTemperatureSetpointHold>(), //
        make_unique<SubscribeAttributeThermostatTemperatureSetpointHold>(), //
        make_unique<ReadThermostatTemperatureSetpointHoldDuration>(), //
        make_unique<WriteThermostatTemperatureSetpointHoldDuration>(), //
        make_unique<SubscribeAttributeThermostatTemperatureSetpointHoldDuration>(), //
        make_unique<ReadThermostatThermostatProgrammingOperationMode>(), //
        make_unique<WriteThermostatThermostatProgrammingOperationMode>(), //
        make_unique<SubscribeAttributeThermostatThermostatProgrammingOperationMode>(), //
        make_unique<ReadThermostatThermostatRunningState>(), //
        make_unique<SubscribeAttributeThermostatThermostatRunningState>(), //
        make_unique<ReadThermostatSetpointChangeSource>(), //
        make_unique<SubscribeAttributeThermostatSetpointChangeSource>(), //
        make_unique<ReadThermostatSetpointChangeAmount>(), //
        make_unique<SubscribeAttributeThermostatSetpointChangeAmount>(), //
        make_unique<ReadThermostatSetpointChangeSourceTimestamp>(), //
        make_unique<SubscribeAttributeThermostatSetpointChangeSourceTimestamp>(), //
        make_unique<ReadThermostatOccupiedSetback>(), //
        make_unique<WriteThermostatOccupiedSetback>(), //
        make_unique<SubscribeAttributeThermostatOccupiedSetback>(), //
        make_unique<ReadThermostatOccupiedSetbackMin>(), //
        make_unique<SubscribeAttributeThermostatOccupiedSetbackMin>(), //
        make_unique<ReadThermostatOccupiedSetbackMax>(), //
        make_unique<SubscribeAttributeThermostatOccupiedSetbackMax>(), //
        make_unique<ReadThermostatUnoccupiedSetback>(), //
        make_unique<WriteThermostatUnoccupiedSetback>(), //
        make_unique<SubscribeAttributeThermostatUnoccupiedSetback>(), //
        make_unique<ReadThermostatUnoccupiedSetbackMin>(), //
        make_unique<SubscribeAttributeThermostatUnoccupiedSetbackMin>(), //
        make_unique<ReadThermostatUnoccupiedSetbackMax>(), //
        make_unique<SubscribeAttributeThermostatUnoccupiedSetbackMax>(), //
        make_unique<ReadThermostatEmergencyHeatDelta>(), //
        make_unique<WriteThermostatEmergencyHeatDelta>(), //
        make_unique<SubscribeAttributeThermostatEmergencyHeatDelta>(), //
        make_unique<ReadThermostatACType>(), //
        make_unique<WriteThermostatACType>(), //
        make_unique<SubscribeAttributeThermostatACType>(), //
        make_unique<ReadThermostatACCapacity>(), //
        make_unique<WriteThermostatACCapacity>(), //
        make_unique<SubscribeAttributeThermostatACCapacity>(), //
        make_unique<ReadThermostatACRefrigerantType>(), //
        make_unique<WriteThermostatACRefrigerantType>(), //
        make_unique<SubscribeAttributeThermostatACRefrigerantType>(), //
        make_unique<ReadThermostatACCompressorType>(), //
        make_unique<WriteThermostatACCompressorType>(), //
        make_unique<SubscribeAttributeThermostatACCompressorType>(), //
        make_unique<ReadThermostatACErrorCode>(), //
        make_unique<WriteThermostatACErrorCode>(), //
        make_unique<SubscribeAttributeThermostatACErrorCode>(), //
        make_unique<ReadThermostatACLouverPosition>(), //
        make_unique<WriteThermostatACLouverPosition>(), //
        make_unique<SubscribeAttributeThermostatACLouverPosition>(), //
        make_unique<ReadThermostatACCoilTemperature>(), //
        make_unique<SubscribeAttributeThermostatACCoilTemperature>(), //
        make_unique<ReadThermostatACCapacityformat>(), //
        make_unique<WriteThermostatACCapacityformat>(), //
        make_unique<SubscribeAttributeThermostatACCapacityformat>(), //
        make_unique<ReadThermostatGeneratedCommandList>(), //
        make_unique<SubscribeAttributeThermostatGeneratedCommandList>(), //
        make_unique<ReadThermostatAcceptedCommandList>(), //
        make_unique<SubscribeAttributeThermostatAcceptedCommandList>(), //
        make_unique<ReadThermostatAttributeList>(), //
        make_unique<SubscribeAttributeThermostatAttributeList>(), //
        make_unique<ReadThermostatFeatureMap>(), //
        make_unique<SubscribeAttributeThermostatFeatureMap>(), //
        make_unique<ReadThermostatClusterRevision>(), //
        make_unique<SubscribeAttributeThermostatClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterFanControl(Commands & commands)
{
    using namespace chip::app::Clusters::FanControl;

    const char * clusterName = "FanControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadFanControlFanMode>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteFanControlFanMode>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeFanControlFanMode>(), //
        make_unique<ReadFanControlFanModeSequence>(), //
        make_unique<WriteFanControlFanModeSequence>(), //
        make_unique<SubscribeAttributeFanControlFanModeSequence>(), //
        make_unique<ReadFanControlPercentSetting>(), //
        make_unique<WriteFanControlPercentSetting>(), //
        make_unique<SubscribeAttributeFanControlPercentSetting>(), //
        make_unique<ReadFanControlPercentCurrent>(), //
        make_unique<SubscribeAttributeFanControlPercentCurrent>(), //
        make_unique<ReadFanControlSpeedMax>(), //
        make_unique<SubscribeAttributeFanControlSpeedMax>(), //
        make_unique<ReadFanControlSpeedSetting>(), //
        make_unique<WriteFanControlSpeedSetting>(), //
        make_unique<SubscribeAttributeFanControlSpeedSetting>(), //
        make_unique<ReadFanControlSpeedCurrent>(), //
        make_unique<SubscribeAttributeFanControlSpeedCurrent>(), //
        make_unique<ReadFanControlRockSupport>(), //
        make_unique<SubscribeAttributeFanControlRockSupport>(), //
        make_unique<ReadFanControlRockSetting>(), //
        make_unique<WriteFanControlRockSetting>(), //
        make_unique<SubscribeAttributeFanControlRockSetting>(), //
        make_unique<ReadFanControlWindSupport>(), //
        make_unique<SubscribeAttributeFanControlWindSupport>(), //
        make_unique<ReadFanControlWindSetting>(), //
        make_unique<WriteFanControlWindSetting>(), //
        make_unique<SubscribeAttributeFanControlWindSetting>(), //
        make_unique<ReadFanControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeFanControlGeneratedCommandList>(), //
        make_unique<ReadFanControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeFanControlAcceptedCommandList>(), //
        make_unique<ReadFanControlAttributeList>(), //
        make_unique<SubscribeAttributeFanControlAttributeList>(), //
        make_unique<ReadFanControlFeatureMap>(), //
        make_unique<SubscribeAttributeFanControlFeatureMap>(), //
        make_unique<ReadFanControlClusterRevision>(), //
        make_unique<SubscribeAttributeFanControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterThermostatUserInterfaceConfiguration(Commands & commands)
{
    using namespace chip::app::Clusters::ThermostatUserInterfaceConfiguration;

    const char * clusterName = "ThermostatUserInterfaceConfiguration";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadThermostatUserInterfaceConfigurationTemperatureDisplayMode>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteThermostatUserInterfaceConfigurationTemperatureDisplayMode>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationTemperatureDisplayMode>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationKeypadLockout>(), //
        make_unique<WriteThermostatUserInterfaceConfigurationKeypadLockout>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationKeypadLockout>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationScheduleProgrammingVisibility>(), //
        make_unique<WriteThermostatUserInterfaceConfigurationScheduleProgrammingVisibility>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationScheduleProgrammingVisibility>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationGeneratedCommandList>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationAcceptedCommandList>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationAttributeList>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationAttributeList>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationFeatureMap>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationFeatureMap>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationClusterRevision>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterColorControl(Commands & commands)
{
    using namespace chip::app::Clusters::ColorControl;

    const char * clusterName = "ColorControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ColorControlMoveToHue>(), //
        make_unique<ColorControlMoveHue>(), //
        make_unique<ColorControlStepHue>(), //
        make_unique<ColorControlMoveToSaturation>(), //
        make_unique<ColorControlMoveSaturation>(), //
        make_unique<ColorControlStepSaturation>(), //
        make_unique<ColorControlMoveToHueAndSaturation>(), //
        make_unique<ColorControlMoveToColor>(), //
        make_unique<ColorControlMoveColor>(), //
        make_unique<ColorControlStepColor>(), //
        make_unique<ColorControlMoveToColorTemperature>(), //
        make_unique<ColorControlEnhancedMoveToHue>(), //
        make_unique<ColorControlEnhancedMoveHue>(), //
        make_unique<ColorControlEnhancedStepHue>(), //
        make_unique<ColorControlEnhancedMoveToHueAndSaturation>(), //
        make_unique<ColorControlColorLoopSet>(), //
        make_unique<ColorControlStopMoveStep>(), //
        make_unique<ColorControlMoveColorTemperature>(), //
        make_unique<ColorControlStepColorTemperature>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadColorControlCurrentHue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeColorControlCurrentHue>(), //
        make_unique<ReadColorControlCurrentSaturation>(), //
        make_unique<SubscribeAttributeColorControlCurrentSaturation>(), //
        make_unique<ReadColorControlRemainingTime>(), //
        make_unique<SubscribeAttributeColorControlRemainingTime>(), //
        make_unique<ReadColorControlCurrentX>(), //
        make_unique<SubscribeAttributeColorControlCurrentX>(), //
        make_unique<ReadColorControlCurrentY>(), //
        make_unique<SubscribeAttributeColorControlCurrentY>(), //
        make_unique<ReadColorControlDriftCompensation>(), //
        make_unique<SubscribeAttributeColorControlDriftCompensation>(), //
        make_unique<ReadColorControlCompensationText>(), //
        make_unique<SubscribeAttributeColorControlCompensationText>(), //
        make_unique<ReadColorControlColorTemperature>(), //
        make_unique<SubscribeAttributeColorControlColorTemperature>(), //
        make_unique<ReadColorControlColorMode>(), //
        make_unique<SubscribeAttributeColorControlColorMode>(), //
        make_unique<ReadColorControlOptions>(), //
        make_unique<WriteColorControlOptions>(), //
        make_unique<SubscribeAttributeColorControlOptions>(), //
        make_unique<ReadColorControlNumberOfPrimaries>(), //
        make_unique<SubscribeAttributeColorControlNumberOfPrimaries>(), //
        make_unique<ReadColorControlPrimary1X>(), //
        make_unique<SubscribeAttributeColorControlPrimary1X>(), //
        make_unique<ReadColorControlPrimary1Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary1Y>(), //
        make_unique<ReadColorControlPrimary1Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary1Intensity>(), //
        make_unique<ReadColorControlPrimary2X>(), //
        make_unique<SubscribeAttributeColorControlPrimary2X>(), //
        make_unique<ReadColorControlPrimary2Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary2Y>(), //
        make_unique<ReadColorControlPrimary2Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary2Intensity>(), //
        make_unique<ReadColorControlPrimary3X>(), //
        make_unique<SubscribeAttributeColorControlPrimary3X>(), //
        make_unique<ReadColorControlPrimary3Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary3Y>(), //
        make_unique<ReadColorControlPrimary3Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary3Intensity>(), //
        make_unique<ReadColorControlPrimary4X>(), //
        make_unique<SubscribeAttributeColorControlPrimary4X>(), //
        make_unique<ReadColorControlPrimary4Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary4Y>(), //
        make_unique<ReadColorControlPrimary4Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary4Intensity>(), //
        make_unique<ReadColorControlPrimary5X>(), //
        make_unique<SubscribeAttributeColorControlPrimary5X>(), //
        make_unique<ReadColorControlPrimary5Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary5Y>(), //
        make_unique<ReadColorControlPrimary5Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary5Intensity>(), //
        make_unique<ReadColorControlPrimary6X>(), //
        make_unique<SubscribeAttributeColorControlPrimary6X>(), //
        make_unique<ReadColorControlPrimary6Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary6Y>(), //
        make_unique<ReadColorControlPrimary6Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary6Intensity>(), //
        make_unique<ReadColorControlWhitePointX>(), //
        make_unique<WriteColorControlWhitePointX>(), //
        make_unique<SubscribeAttributeColorControlWhitePointX>(), //
        make_unique<ReadColorControlWhitePointY>(), //
        make_unique<WriteColorControlWhitePointY>(), //
        make_unique<SubscribeAttributeColorControlWhitePointY>(), //
        make_unique<ReadColorControlColorPointRX>(), //
        make_unique<WriteColorControlColorPointRX>(), //
        make_unique<SubscribeAttributeColorControlColorPointRX>(), //
        make_unique<ReadColorControlColorPointRY>(), //
        make_unique<WriteColorControlColorPointRY>(), //
        make_unique<SubscribeAttributeColorControlColorPointRY>(), //
        make_unique<ReadColorControlColorPointRIntensity>(), //
        make_unique<WriteColorControlColorPointRIntensity>(), //
        make_unique<SubscribeAttributeColorControlColorPointRIntensity>(), //
        make_unique<ReadColorControlColorPointGX>(), //
        make_unique<WriteColorControlColorPointGX>(), //
        make_unique<SubscribeAttributeColorControlColorPointGX>(), //
        make_unique<ReadColorControlColorPointGY>(), //
        make_unique<WriteColorControlColorPointGY>(), //
        make_unique<SubscribeAttributeColorControlColorPointGY>(), //
        make_unique<ReadColorControlColorPointGIntensity>(), //
        make_unique<WriteColorControlColorPointGIntensity>(), //
        make_unique<SubscribeAttributeColorControlColorPointGIntensity>(), //
        make_unique<ReadColorControlColorPointBX>(), //
        make_unique<WriteColorControlColorPointBX>(), //
        make_unique<SubscribeAttributeColorControlColorPointBX>(), //
        make_unique<ReadColorControlColorPointBY>(), //
        make_unique<WriteColorControlColorPointBY>(), //
        make_unique<SubscribeAttributeColorControlColorPointBY>(), //
        make_unique<ReadColorControlColorPointBIntensity>(), //
        make_unique<WriteColorControlColorPointBIntensity>(), //
        make_unique<SubscribeAttributeColorControlColorPointBIntensity>(), //
        make_unique<ReadColorControlEnhancedCurrentHue>(), //
        make_unique<SubscribeAttributeColorControlEnhancedCurrentHue>(), //
        make_unique<ReadColorControlEnhancedColorMode>(), //
        make_unique<SubscribeAttributeColorControlEnhancedColorMode>(), //
        make_unique<ReadColorControlColorLoopActive>(), //
        make_unique<SubscribeAttributeColorControlColorLoopActive>(), //
        make_unique<ReadColorControlColorLoopDirection>(), //
        make_unique<SubscribeAttributeColorControlColorLoopDirection>(), //
        make_unique<ReadColorControlColorLoopTime>(), //
        make_unique<SubscribeAttributeColorControlColorLoopTime>(), //
        make_unique<ReadColorControlColorLoopStartEnhancedHue>(), //
        make_unique<SubscribeAttributeColorControlColorLoopStartEnhancedHue>(), //
        make_unique<ReadColorControlColorLoopStoredEnhancedHue>(), //
        make_unique<SubscribeAttributeColorControlColorLoopStoredEnhancedHue>(), //
        make_unique<ReadColorControlColorCapabilities>(), //
        make_unique<SubscribeAttributeColorControlColorCapabilities>(), //
        make_unique<ReadColorControlColorTempPhysicalMinMireds>(), //
        make_unique<SubscribeAttributeColorControlColorTempPhysicalMinMireds>(), //
        make_unique<ReadColorControlColorTempPhysicalMaxMireds>(), //
        make_unique<SubscribeAttributeColorControlColorTempPhysicalMaxMireds>(), //
        make_unique<ReadColorControlCoupleColorTempToLevelMinMireds>(), //
        make_unique<SubscribeAttributeColorControlCoupleColorTempToLevelMinMireds>(), //
        make_unique<ReadColorControlStartUpColorTemperatureMireds>(), //
        make_unique<WriteColorControlStartUpColorTemperatureMireds>(), //
        make_unique<SubscribeAttributeColorControlStartUpColorTemperatureMireds>(), //
        make_unique<ReadColorControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeColorControlGeneratedCommandList>(), //
        make_unique<ReadColorControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeColorControlAcceptedCommandList>(), //
        make_unique<ReadColorControlAttributeList>(), //
        make_unique<SubscribeAttributeColorControlAttributeList>(), //
        make_unique<ReadColorControlFeatureMap>(), //
        make_unique<SubscribeAttributeColorControlFeatureMap>(), //
        make_unique<ReadColorControlClusterRevision>(), //
        make_unique<SubscribeAttributeColorControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBallastConfiguration(Commands & commands)
{
    using namespace chip::app::Clusters::BallastConfiguration;

    const char * clusterName = "BallastConfiguration";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBallastConfigurationPhysicalMinLevel>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBallastConfigurationPhysicalMinLevel>(), //
        make_unique<ReadBallastConfigurationPhysicalMaxLevel>(), //
        make_unique<SubscribeAttributeBallastConfigurationPhysicalMaxLevel>(), //
        make_unique<ReadBallastConfigurationBallastStatus>(), //
        make_unique<SubscribeAttributeBallastConfigurationBallastStatus>(), //
        make_unique<ReadBallastConfigurationMinLevel>(), //
        make_unique<WriteBallastConfigurationMinLevel>(), //
        make_unique<SubscribeAttributeBallastConfigurationMinLevel>(), //
        make_unique<ReadBallastConfigurationMaxLevel>(), //
        make_unique<WriteBallastConfigurationMaxLevel>(), //
        make_unique<SubscribeAttributeBallastConfigurationMaxLevel>(), //
        make_unique<ReadBallastConfigurationIntrinsicBalanceFactor>(), //
        make_unique<WriteBallastConfigurationIntrinsicBalanceFactor>(), //
        make_unique<SubscribeAttributeBallastConfigurationIntrinsicBalanceFactor>(), //
        make_unique<ReadBallastConfigurationBallastFactorAdjustment>(), //
        make_unique<WriteBallastConfigurationBallastFactorAdjustment>(), //
        make_unique<SubscribeAttributeBallastConfigurationBallastFactorAdjustment>(), //
        make_unique<ReadBallastConfigurationLampQuantity>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampQuantity>(), //
        make_unique<ReadBallastConfigurationLampType>(), //
        make_unique<WriteBallastConfigurationLampType>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampType>(), //
        make_unique<ReadBallastConfigurationLampManufacturer>(), //
        make_unique<WriteBallastConfigurationLampManufacturer>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampManufacturer>(), //
        make_unique<ReadBallastConfigurationLampRatedHours>(), //
        make_unique<WriteBallastConfigurationLampRatedHours>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampRatedHours>(), //
        make_unique<ReadBallastConfigurationLampBurnHours>(), //
        make_unique<WriteBallastConfigurationLampBurnHours>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampBurnHours>(), //
        make_unique<ReadBallastConfigurationLampAlarmMode>(), //
        make_unique<WriteBallastConfigurationLampAlarmMode>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampAlarmMode>(), //
        make_unique<ReadBallastConfigurationLampBurnHoursTripPoint>(), //
        make_unique<WriteBallastConfigurationLampBurnHoursTripPoint>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampBurnHoursTripPoint>(), //
        make_unique<ReadBallastConfigurationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBallastConfigurationGeneratedCommandList>(), //
        make_unique<ReadBallastConfigurationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBallastConfigurationAcceptedCommandList>(), //
        make_unique<ReadBallastConfigurationAttributeList>(), //
        make_unique<SubscribeAttributeBallastConfigurationAttributeList>(), //
        make_unique<ReadBallastConfigurationFeatureMap>(), //
        make_unique<SubscribeAttributeBallastConfigurationFeatureMap>(), //
        make_unique<ReadBallastConfigurationClusterRevision>(), //
        make_unique<SubscribeAttributeBallastConfigurationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterIlluminanceMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::IlluminanceMeasurement;

    const char * clusterName = "IlluminanceMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadIlluminanceMeasurementMeasuredValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeIlluminanceMeasurementMeasuredValue>(), //
        make_unique<ReadIlluminanceMeasurementMinMeasuredValue>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementMinMeasuredValue>(), //
        make_unique<ReadIlluminanceMeasurementMaxMeasuredValue>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementMaxMeasuredValue>(), //
        make_unique<ReadIlluminanceMeasurementTolerance>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementTolerance>(), //
        make_unique<ReadIlluminanceMeasurementLightSensorType>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementLightSensorType>(), //
        make_unique<ReadIlluminanceMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementGeneratedCommandList>(), //
        make_unique<ReadIlluminanceMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementAcceptedCommandList>(), //
        make_unique<ReadIlluminanceMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementAttributeList>(), //
        make_unique<ReadIlluminanceMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementFeatureMap>(), //
        make_unique<ReadIlluminanceMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterTemperatureMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::TemperatureMeasurement;

    const char * clusterName = "TemperatureMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadTemperatureMeasurementMeasuredValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeTemperatureMeasurementMeasuredValue>(), //
        make_unique<ReadTemperatureMeasurementMinMeasuredValue>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementMinMeasuredValue>(), //
        make_unique<ReadTemperatureMeasurementMaxMeasuredValue>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementMaxMeasuredValue>(), //
        make_unique<ReadTemperatureMeasurementTolerance>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementTolerance>(), //
        make_unique<ReadTemperatureMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementGeneratedCommandList>(), //
        make_unique<ReadTemperatureMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementAcceptedCommandList>(), //
        make_unique<ReadTemperatureMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementAttributeList>(), //
        make_unique<ReadTemperatureMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementFeatureMap>(), //
        make_unique<ReadTemperatureMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterPressureMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::PressureMeasurement;

    const char * clusterName = "PressureMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadPressureMeasurementMeasuredValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributePressureMeasurementMeasuredValue>(), //
        make_unique<ReadPressureMeasurementMinMeasuredValue>(), //
        make_unique<SubscribeAttributePressureMeasurementMinMeasuredValue>(), //
        make_unique<ReadPressureMeasurementMaxMeasuredValue>(), //
        make_unique<SubscribeAttributePressureMeasurementMaxMeasuredValue>(), //
        make_unique<ReadPressureMeasurementTolerance>(), //
        make_unique<SubscribeAttributePressureMeasurementTolerance>(), //
        make_unique<ReadPressureMeasurementScaledValue>(), //
        make_unique<SubscribeAttributePressureMeasurementScaledValue>(), //
        make_unique<ReadPressureMeasurementMinScaledValue>(), //
        make_unique<SubscribeAttributePressureMeasurementMinScaledValue>(), //
        make_unique<ReadPressureMeasurementMaxScaledValue>(), //
        make_unique<SubscribeAttributePressureMeasurementMaxScaledValue>(), //
        make_unique<ReadPressureMeasurementScaledTolerance>(), //
        make_unique<SubscribeAttributePressureMeasurementScaledTolerance>(), //
        make_unique<ReadPressureMeasurementScale>(), //
        make_unique<SubscribeAttributePressureMeasurementScale>(), //
        make_unique<ReadPressureMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributePressureMeasurementGeneratedCommandList>(), //
        make_unique<ReadPressureMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributePressureMeasurementAcceptedCommandList>(), //
        make_unique<ReadPressureMeasurementAttributeList>(), //
        make_unique<SubscribeAttributePressureMeasurementAttributeList>(), //
        make_unique<ReadPressureMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributePressureMeasurementFeatureMap>(), //
        make_unique<ReadPressureMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributePressureMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterFlowMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::FlowMeasurement;

    const char * clusterName = "FlowMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadFlowMeasurementMeasuredValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeFlowMeasurementMeasuredValue>(), //
        make_unique<ReadFlowMeasurementMinMeasuredValue>(), //
        make_unique<SubscribeAttributeFlowMeasurementMinMeasuredValue>(), //
        make_unique<ReadFlowMeasurementMaxMeasuredValue>(), //
        make_unique<SubscribeAttributeFlowMeasurementMaxMeasuredValue>(), //
        make_unique<ReadFlowMeasurementTolerance>(), //
        make_unique<SubscribeAttributeFlowMeasurementTolerance>(), //
        make_unique<ReadFlowMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeFlowMeasurementGeneratedCommandList>(), //
        make_unique<ReadFlowMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeFlowMeasurementAcceptedCommandList>(), //
        make_unique<ReadFlowMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeFlowMeasurementAttributeList>(), //
        make_unique<ReadFlowMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeFlowMeasurementFeatureMap>(), //
        make_unique<ReadFlowMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeFlowMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterRelativeHumidityMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::RelativeHumidityMeasurement;

    const char * clusterName = "RelativeHumidityMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadRelativeHumidityMeasurementMeasuredValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementMeasuredValue>(), //
        make_unique<ReadRelativeHumidityMeasurementMinMeasuredValue>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementMinMeasuredValue>(), //
        make_unique<ReadRelativeHumidityMeasurementMaxMeasuredValue>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementMaxMeasuredValue>(), //
        make_unique<ReadRelativeHumidityMeasurementTolerance>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementTolerance>(), //
        make_unique<ReadRelativeHumidityMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementGeneratedCommandList>(), //
        make_unique<ReadRelativeHumidityMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementAcceptedCommandList>(), //
        make_unique<ReadRelativeHumidityMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementAttributeList>(), //
        make_unique<ReadRelativeHumidityMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementFeatureMap>(), //
        make_unique<ReadRelativeHumidityMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOccupancySensing(Commands & commands)
{
    using namespace chip::app::Clusters::OccupancySensing;

    const char * clusterName = "OccupancySensing";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOccupancySensingOccupancy>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOccupancySensingOccupancy>(), //
        make_unique<ReadOccupancySensingOccupancySensorType>(), //
        make_unique<SubscribeAttributeOccupancySensingOccupancySensorType>(), //
        make_unique<ReadOccupancySensingOccupancySensorTypeBitmap>(), //
        make_unique<SubscribeAttributeOccupancySensingOccupancySensorTypeBitmap>(), //
        make_unique<ReadOccupancySensingPirOccupiedToUnoccupiedDelay>(), //
        make_unique<WriteOccupancySensingPirOccupiedToUnoccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingPirOccupiedToUnoccupiedDelay>(), //
        make_unique<ReadOccupancySensingPirUnoccupiedToOccupiedDelay>(), //
        make_unique<WriteOccupancySensingPirUnoccupiedToOccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedDelay>(), //
        make_unique<ReadOccupancySensingPirUnoccupiedToOccupiedThreshold>(), //
        make_unique<WriteOccupancySensingPirUnoccupiedToOccupiedThreshold>(), //
        make_unique<SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedThreshold>(), //
        make_unique<ReadOccupancySensingUltrasonicOccupiedToUnoccupiedDelay>(), //
        make_unique<WriteOccupancySensingUltrasonicOccupiedToUnoccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingUltrasonicOccupiedToUnoccupiedDelay>(), //
        make_unique<ReadOccupancySensingUltrasonicUnoccupiedToOccupiedDelay>(), //
        make_unique<WriteOccupancySensingUltrasonicUnoccupiedToOccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedDelay>(), //
        make_unique<ReadOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold>(), //
        make_unique<WriteOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold>(), //
        make_unique<SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold>(), //
        make_unique<ReadOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay>(), //
        make_unique<WriteOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay>(), //
        make_unique<ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay>(), //
        make_unique<WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay>(), //
        make_unique<ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold>(), //
        make_unique<WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold>(), //
        make_unique<SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold>(), //
        make_unique<ReadOccupancySensingGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOccupancySensingGeneratedCommandList>(), //
        make_unique<ReadOccupancySensingAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOccupancySensingAcceptedCommandList>(), //
        make_unique<ReadOccupancySensingAttributeList>(), //
        make_unique<SubscribeAttributeOccupancySensingAttributeList>(), //
        make_unique<ReadOccupancySensingFeatureMap>(), //
        make_unique<SubscribeAttributeOccupancySensingFeatureMap>(), //
        make_unique<ReadOccupancySensingClusterRevision>(), //
        make_unique<SubscribeAttributeOccupancySensingClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterWakeOnLan(Commands & commands)
{
    using namespace chip::app::Clusters::WakeOnLan;

    const char * clusterName = "WakeOnLan";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadWakeOnLanMACAddress>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeWakeOnLanMACAddress>(), //
        make_unique<ReadWakeOnLanGeneratedCommandList>(), //
        make_unique<SubscribeAttributeWakeOnLanGeneratedCommandList>(), //
        make_unique<ReadWakeOnLanAcceptedCommandList>(), //
        make_unique<SubscribeAttributeWakeOnLanAcceptedCommandList>(), //
        make_unique<ReadWakeOnLanAttributeList>(), //
        make_unique<SubscribeAttributeWakeOnLanAttributeList>(), //
        make_unique<ReadWakeOnLanFeatureMap>(), //
        make_unique<SubscribeAttributeWakeOnLanFeatureMap>(), //
        make_unique<ReadWakeOnLanClusterRevision>(), //
        make_unique<SubscribeAttributeWakeOnLanClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterChannel(Commands & commands)
{
    using namespace chip::app::Clusters::Channel;

    const char * clusterName = "Channel";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ChannelChangeChannel>(), //
        make_unique<ChannelChangeChannelByNumber>(), //
        make_unique<ChannelSkipChannel>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadChannelChannelList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeChannelChannelList>(), //
        make_unique<ReadChannelLineup>(), //
        make_unique<SubscribeAttributeChannelLineup>(), //
        make_unique<ReadChannelCurrentChannel>(), //
        make_unique<SubscribeAttributeChannelCurrentChannel>(), //
        make_unique<ReadChannelGeneratedCommandList>(), //
        make_unique<SubscribeAttributeChannelGeneratedCommandList>(), //
        make_unique<ReadChannelAcceptedCommandList>(), //
        make_unique<SubscribeAttributeChannelAcceptedCommandList>(), //
        make_unique<ReadChannelAttributeList>(), //
        make_unique<SubscribeAttributeChannelAttributeList>(), //
        make_unique<ReadChannelFeatureMap>(), //
        make_unique<SubscribeAttributeChannelFeatureMap>(), //
        make_unique<ReadChannelClusterRevision>(), //
        make_unique<SubscribeAttributeChannelClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterTargetNavigator(Commands & commands)
{
    using namespace chip::app::Clusters::TargetNavigator;

    const char * clusterName = "TargetNavigator";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<TargetNavigatorNavigateTarget>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadTargetNavigatorTargetList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeTargetNavigatorTargetList>(), //
        make_unique<ReadTargetNavigatorCurrentTarget>(), //
        make_unique<SubscribeAttributeTargetNavigatorCurrentTarget>(), //
        make_unique<ReadTargetNavigatorGeneratedCommandList>(), //
        make_unique<SubscribeAttributeTargetNavigatorGeneratedCommandList>(), //
        make_unique<ReadTargetNavigatorAcceptedCommandList>(), //
        make_unique<SubscribeAttributeTargetNavigatorAcceptedCommandList>(), //
        make_unique<ReadTargetNavigatorAttributeList>(), //
        make_unique<SubscribeAttributeTargetNavigatorAttributeList>(), //
        make_unique<ReadTargetNavigatorFeatureMap>(), //
        make_unique<SubscribeAttributeTargetNavigatorFeatureMap>(), //
        make_unique<ReadTargetNavigatorClusterRevision>(), //
        make_unique<SubscribeAttributeTargetNavigatorClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterMediaPlayback(Commands & commands)
{
    using namespace chip::app::Clusters::MediaPlayback;

    const char * clusterName = "MediaPlayback";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<MediaPlaybackPlay>(), //
        make_unique<MediaPlaybackPause>(), //
        make_unique<MediaPlaybackStopPlayback>(), //
        make_unique<MediaPlaybackStartOver>(), //
        make_unique<MediaPlaybackPrevious>(), //
        make_unique<MediaPlaybackNext>(), //
        make_unique<MediaPlaybackRewind>(), //
        make_unique<MediaPlaybackFastForward>(), //
        make_unique<MediaPlaybackSkipForward>(), //
        make_unique<MediaPlaybackSkipBackward>(), //
        make_unique<MediaPlaybackSeek>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadMediaPlaybackCurrentState>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeMediaPlaybackCurrentState>(), //
        make_unique<ReadMediaPlaybackStartTime>(), //
        make_unique<SubscribeAttributeMediaPlaybackStartTime>(), //
        make_unique<ReadMediaPlaybackDuration>(), //
        make_unique<SubscribeAttributeMediaPlaybackDuration>(), //
        make_unique<ReadMediaPlaybackSampledPosition>(), //
        make_unique<SubscribeAttributeMediaPlaybackSampledPosition>(), //
        make_unique<ReadMediaPlaybackPlaybackSpeed>(), //
        make_unique<SubscribeAttributeMediaPlaybackPlaybackSpeed>(), //
        make_unique<ReadMediaPlaybackSeekRangeEnd>(), //
        make_unique<SubscribeAttributeMediaPlaybackSeekRangeEnd>(), //
        make_unique<ReadMediaPlaybackSeekRangeStart>(), //
        make_unique<SubscribeAttributeMediaPlaybackSeekRangeStart>(), //
        make_unique<ReadMediaPlaybackGeneratedCommandList>(), //
        make_unique<SubscribeAttributeMediaPlaybackGeneratedCommandList>(), //
        make_unique<ReadMediaPlaybackAcceptedCommandList>(), //
        make_unique<SubscribeAttributeMediaPlaybackAcceptedCommandList>(), //
        make_unique<ReadMediaPlaybackAttributeList>(), //
        make_unique<SubscribeAttributeMediaPlaybackAttributeList>(), //
        make_unique<ReadMediaPlaybackFeatureMap>(), //
        make_unique<SubscribeAttributeMediaPlaybackFeatureMap>(), //
        make_unique<ReadMediaPlaybackClusterRevision>(), //
        make_unique<SubscribeAttributeMediaPlaybackClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterMediaInput(Commands & commands)
{
    using namespace chip::app::Clusters::MediaInput;

    const char * clusterName = "MediaInput";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<MediaInputSelectInput>(), //
        make_unique<MediaInputShowInputStatus>(), //
        make_unique<MediaInputHideInputStatus>(), //
        make_unique<MediaInputRenameInput>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadMediaInputInputList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeMediaInputInputList>(), //
        make_unique<ReadMediaInputCurrentInput>(), //
        make_unique<SubscribeAttributeMediaInputCurrentInput>(), //
        make_unique<ReadMediaInputGeneratedCommandList>(), //
        make_unique<SubscribeAttributeMediaInputGeneratedCommandList>(), //
        make_unique<ReadMediaInputAcceptedCommandList>(), //
        make_unique<SubscribeAttributeMediaInputAcceptedCommandList>(), //
        make_unique<ReadMediaInputAttributeList>(), //
        make_unique<SubscribeAttributeMediaInputAttributeList>(), //
        make_unique<ReadMediaInputFeatureMap>(), //
        make_unique<SubscribeAttributeMediaInputFeatureMap>(), //
        make_unique<ReadMediaInputClusterRevision>(), //
        make_unique<SubscribeAttributeMediaInputClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterLowPower(Commands & commands)
{
    using namespace chip::app::Clusters::LowPower;

    const char * clusterName = "LowPower";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<LowPowerSleep>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadLowPowerGeneratedCommandList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeLowPowerGeneratedCommandList>(), //
        make_unique<ReadLowPowerAcceptedCommandList>(), //
        make_unique<SubscribeAttributeLowPowerAcceptedCommandList>(), //
        make_unique<ReadLowPowerAttributeList>(), //
        make_unique<SubscribeAttributeLowPowerAttributeList>(), //
        make_unique<ReadLowPowerFeatureMap>(), //
        make_unique<SubscribeAttributeLowPowerFeatureMap>(), //
        make_unique<ReadLowPowerClusterRevision>(), //
        make_unique<SubscribeAttributeLowPowerClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterKeypadInput(Commands & commands)
{
    using namespace chip::app::Clusters::KeypadInput;

    const char * clusterName = "KeypadInput";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<KeypadInputSendKey>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadKeypadInputGeneratedCommandList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeKeypadInputGeneratedCommandList>(), //
        make_unique<ReadKeypadInputAcceptedCommandList>(), //
        make_unique<SubscribeAttributeKeypadInputAcceptedCommandList>(), //
        make_unique<ReadKeypadInputAttributeList>(), //
        make_unique<SubscribeAttributeKeypadInputAttributeList>(), //
        make_unique<ReadKeypadInputFeatureMap>(), //
        make_unique<SubscribeAttributeKeypadInputFeatureMap>(), //
        make_unique<ReadKeypadInputClusterRevision>(), //
        make_unique<SubscribeAttributeKeypadInputClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterContentLauncher(Commands & commands)
{
    using namespace chip::app::Clusters::ContentLauncher;

    const char * clusterName = "ContentLauncher";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ContentLauncherLaunchContent>(), //
        make_unique<ContentLauncherLaunchURL>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadContentLauncherAcceptHeader>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeContentLauncherAcceptHeader>(), //
        make_unique<ReadContentLauncherSupportedStreamingProtocols>(), //
        make_unique<WriteContentLauncherSupportedStreamingProtocols>(), //
        make_unique<SubscribeAttributeContentLauncherSupportedStreamingProtocols>(), //
        make_unique<ReadContentLauncherGeneratedCommandList>(), //
        make_unique<SubscribeAttributeContentLauncherGeneratedCommandList>(), //
        make_unique<ReadContentLauncherAcceptedCommandList>(), //
        make_unique<SubscribeAttributeContentLauncherAcceptedCommandList>(), //
        make_unique<ReadContentLauncherAttributeList>(), //
        make_unique<SubscribeAttributeContentLauncherAttributeList>(), //
        make_unique<ReadContentLauncherFeatureMap>(), //
        make_unique<SubscribeAttributeContentLauncherFeatureMap>(), //
        make_unique<ReadContentLauncherClusterRevision>(), //
        make_unique<SubscribeAttributeContentLauncherClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterAudioOutput(Commands & commands)
{
    using namespace chip::app::Clusters::AudioOutput;

    const char * clusterName = "AudioOutput";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<AudioOutputSelectOutput>(), //
        make_unique<AudioOutputRenameOutput>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadAudioOutputOutputList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeAudioOutputOutputList>(), //
        make_unique<ReadAudioOutputCurrentOutput>(), //
        make_unique<SubscribeAttributeAudioOutputCurrentOutput>(), //
        make_unique<ReadAudioOutputGeneratedCommandList>(), //
        make_unique<SubscribeAttributeAudioOutputGeneratedCommandList>(), //
        make_unique<ReadAudioOutputAcceptedCommandList>(), //
        make_unique<SubscribeAttributeAudioOutputAcceptedCommandList>(), //
        make_unique<ReadAudioOutputAttributeList>(), //
        make_unique<SubscribeAttributeAudioOutputAttributeList>(), //
        make_unique<ReadAudioOutputFeatureMap>(), //
        make_unique<SubscribeAttributeAudioOutputFeatureMap>(), //
        make_unique<ReadAudioOutputClusterRevision>(), //
        make_unique<SubscribeAttributeAudioOutputClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterApplicationLauncher(Commands & commands)
{
    using namespace chip::app::Clusters::ApplicationLauncher;

    const char * clusterName = "ApplicationLauncher";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ApplicationLauncherLaunchApp>(), //
        make_unique<ApplicationLauncherStopApp>(), //
        make_unique<ApplicationLauncherHideApp>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadApplicationLauncherCatalogList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeApplicationLauncherCatalogList>(), //
        make_unique<ReadApplicationLauncherCurrentApp>(), //
        make_unique<WriteApplicationLauncherCurrentApp>(), //
        make_unique<SubscribeAttributeApplicationLauncherCurrentApp>(), //
        make_unique<ReadApplicationLauncherGeneratedCommandList>(), //
        make_unique<SubscribeAttributeApplicationLauncherGeneratedCommandList>(), //
        make_unique<ReadApplicationLauncherAcceptedCommandList>(), //
        make_unique<SubscribeAttributeApplicationLauncherAcceptedCommandList>(), //
        make_unique<ReadApplicationLauncherAttributeList>(), //
        make_unique<SubscribeAttributeApplicationLauncherAttributeList>(), //
        make_unique<ReadApplicationLauncherFeatureMap>(), //
        make_unique<SubscribeAttributeApplicationLauncherFeatureMap>(), //
        make_unique<ReadApplicationLauncherClusterRevision>(), //
        make_unique<SubscribeAttributeApplicationLauncherClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterApplicationBasic(Commands & commands)
{
    using namespace chip::app::Clusters::ApplicationBasic;

    const char * clusterName = "ApplicationBasic";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadApplicationBasicVendorName>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeApplicationBasicVendorName>(), //
        make_unique<ReadApplicationBasicVendorID>(), //
        make_unique<SubscribeAttributeApplicationBasicVendorID>(), //
        make_unique<ReadApplicationBasicApplicationName>(), //
        make_unique<SubscribeAttributeApplicationBasicApplicationName>(), //
        make_unique<ReadApplicationBasicProductID>(), //
        make_unique<SubscribeAttributeApplicationBasicProductID>(), //
        make_unique<ReadApplicationBasicApplication>(), //
        make_unique<SubscribeAttributeApplicationBasicApplication>(), //
        make_unique<ReadApplicationBasicStatus>(), //
        make_unique<SubscribeAttributeApplicationBasicStatus>(), //
        make_unique<ReadApplicationBasicApplicationVersion>(), //
        make_unique<SubscribeAttributeApplicationBasicApplicationVersion>(), //
        make_unique<ReadApplicationBasicAllowedVendorList>(), //
        make_unique<SubscribeAttributeApplicationBasicAllowedVendorList>(), //
        make_unique<ReadApplicationBasicGeneratedCommandList>(), //
        make_unique<SubscribeAttributeApplicationBasicGeneratedCommandList>(), //
        make_unique<ReadApplicationBasicAcceptedCommandList>(), //
        make_unique<SubscribeAttributeApplicationBasicAcceptedCommandList>(), //
        make_unique<ReadApplicationBasicAttributeList>(), //
        make_unique<SubscribeAttributeApplicationBasicAttributeList>(), //
        make_unique<ReadApplicationBasicFeatureMap>(), //
        make_unique<SubscribeAttributeApplicationBasicFeatureMap>(), //
        make_unique<ReadApplicationBasicClusterRevision>(), //
        make_unique<SubscribeAttributeApplicationBasicClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterAccountLogin(Commands & commands)
{
    using namespace chip::app::Clusters::AccountLogin;

    const char * clusterName = "AccountLogin";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<AccountLoginGetSetupPIN>(), //
        make_unique<AccountLoginLogin>(), //
        make_unique<AccountLoginLogout>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadAccountLoginGeneratedCommandList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeAccountLoginGeneratedCommandList>(), //
        make_unique<ReadAccountLoginAcceptedCommandList>(), //
        make_unique<SubscribeAttributeAccountLoginAcceptedCommandList>(), //
        make_unique<ReadAccountLoginAttributeList>(), //
        make_unique<SubscribeAttributeAccountLoginAttributeList>(), //
        make_unique<ReadAccountLoginFeatureMap>(), //
        make_unique<SubscribeAttributeAccountLoginFeatureMap>(), //
        make_unique<ReadAccountLoginClusterRevision>(), //
        make_unique<SubscribeAttributeAccountLoginClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterElectricalMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::ElectricalMeasurement;

    const char * clusterName = "ElectricalMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ElectricalMeasurementGetProfileInfoCommand>(), //
        make_unique<ElectricalMeasurementGetMeasurementProfileCommand>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadElectricalMeasurementMeasurementType>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasurementType>(), //
        make_unique<ReadElectricalMeasurementDcVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcVoltage>(), //
        make_unique<ReadElectricalMeasurementDcVoltageMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcVoltageMin>(), //
        make_unique<ReadElectricalMeasurementDcVoltageMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcVoltageMax>(), //
        make_unique<ReadElectricalMeasurementDcCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcCurrent>(), //
        make_unique<ReadElectricalMeasurementDcCurrentMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcCurrentMin>(), //
        make_unique<ReadElectricalMeasurementDcCurrentMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcCurrentMax>(), //
        make_unique<ReadElectricalMeasurementDcPower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcPower>(), //
        make_unique<ReadElectricalMeasurementDcPowerMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcPowerMin>(), //
        make_unique<ReadElectricalMeasurementDcPowerMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcPowerMax>(), //
        make_unique<ReadElectricalMeasurementDcVoltageMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcVoltageMultiplier>(), //
        make_unique<ReadElectricalMeasurementDcVoltageDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcVoltageDivisor>(), //
        make_unique<ReadElectricalMeasurementDcCurrentMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcCurrentMultiplier>(), //
        make_unique<ReadElectricalMeasurementDcCurrentDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcCurrentDivisor>(), //
        make_unique<ReadElectricalMeasurementDcPowerMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcPowerMultiplier>(), //
        make_unique<ReadElectricalMeasurementDcPowerDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcPowerDivisor>(), //
        make_unique<ReadElectricalMeasurementAcFrequency>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcFrequency>(), //
        make_unique<ReadElectricalMeasurementAcFrequencyMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcFrequencyMin>(), //
        make_unique<ReadElectricalMeasurementAcFrequencyMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcFrequencyMax>(), //
        make_unique<ReadElectricalMeasurementNeutralCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementNeutralCurrent>(), //
        make_unique<ReadElectricalMeasurementTotalActivePower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementTotalActivePower>(), //
        make_unique<ReadElectricalMeasurementTotalReactivePower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementTotalReactivePower>(), //
        make_unique<ReadElectricalMeasurementTotalApparentPower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementTotalApparentPower>(), //
        make_unique<ReadElectricalMeasurementMeasured1stHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured1stHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasured3rdHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured3rdHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasured5thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured5thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasured7thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured7thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasured9thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured9thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasured11thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured11thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase1stHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase1stHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase3rdHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase3rdHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase5thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase5thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase7thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase7thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase9thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase9thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase11thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase11thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementAcFrequencyMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcFrequencyMultiplier>(), //
        make_unique<ReadElectricalMeasurementAcFrequencyDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcFrequencyDivisor>(), //
        make_unique<ReadElectricalMeasurementPowerMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPowerMultiplier>(), //
        make_unique<ReadElectricalMeasurementPowerDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPowerDivisor>(), //
        make_unique<ReadElectricalMeasurementHarmonicCurrentMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementHarmonicCurrentMultiplier>(), //
        make_unique<ReadElectricalMeasurementPhaseHarmonicCurrentMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPhaseHarmonicCurrentMultiplier>(), //
        make_unique<ReadElectricalMeasurementInstantaneousVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementInstantaneousVoltage>(), //
        make_unique<ReadElectricalMeasurementInstantaneousLineCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementInstantaneousLineCurrent>(), //
        make_unique<ReadElectricalMeasurementInstantaneousActiveCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementInstantaneousActiveCurrent>(), //
        make_unique<ReadElectricalMeasurementInstantaneousReactiveCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementInstantaneousReactiveCurrent>(), //
        make_unique<ReadElectricalMeasurementInstantaneousPower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementInstantaneousPower>(), //
        make_unique<ReadElectricalMeasurementRmsVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltage>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMin>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMax>(), //
        make_unique<ReadElectricalMeasurementRmsCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrent>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMin>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMax>(), //
        make_unique<ReadElectricalMeasurementActivePower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePower>(), //
        make_unique<ReadElectricalMeasurementActivePowerMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMin>(), //
        make_unique<ReadElectricalMeasurementActivePowerMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMax>(), //
        make_unique<ReadElectricalMeasurementReactivePower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementReactivePower>(), //
        make_unique<ReadElectricalMeasurementApparentPower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementApparentPower>(), //
        make_unique<ReadElectricalMeasurementPowerFactor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPowerFactor>(), //
        make_unique<ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriod>(), //
        make_unique<WriteElectricalMeasurementAverageRmsVoltageMeasurementPeriod>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriod>(), //
        make_unique<ReadElectricalMeasurementAverageRmsUnderVoltageCounter>(), //
        make_unique<WriteElectricalMeasurementAverageRmsUnderVoltageCounter>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounter>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeOverVoltagePeriod>(), //
        make_unique<WriteElectricalMeasurementRmsExtremeOverVoltagePeriod>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriod>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeUnderVoltagePeriod>(), //
        make_unique<WriteElectricalMeasurementRmsExtremeUnderVoltagePeriod>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriod>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSagPeriod>(), //
        make_unique<WriteElectricalMeasurementRmsVoltageSagPeriod>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriod>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSwellPeriod>(), //
        make_unique<WriteElectricalMeasurementRmsVoltageSwellPeriod>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriod>(), //
        make_unique<ReadElectricalMeasurementAcVoltageMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcVoltageMultiplier>(), //
        make_unique<ReadElectricalMeasurementAcVoltageDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcVoltageDivisor>(), //
        make_unique<ReadElectricalMeasurementAcCurrentMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcCurrentMultiplier>(), //
        make_unique<ReadElectricalMeasurementAcCurrentDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcCurrentDivisor>(), //
        make_unique<ReadElectricalMeasurementAcPowerMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcPowerMultiplier>(), //
        make_unique<ReadElectricalMeasurementAcPowerDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcPowerDivisor>(), //
        make_unique<ReadElectricalMeasurementOverloadAlarmsMask>(), //
        make_unique<WriteElectricalMeasurementOverloadAlarmsMask>(), //
        make_unique<SubscribeAttributeElectricalMeasurementOverloadAlarmsMask>(), //
        make_unique<ReadElectricalMeasurementVoltageOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementVoltageOverload>(), //
        make_unique<ReadElectricalMeasurementCurrentOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementCurrentOverload>(), //
        make_unique<ReadElectricalMeasurementAcOverloadAlarmsMask>(), //
        make_unique<WriteElectricalMeasurementAcOverloadAlarmsMask>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcOverloadAlarmsMask>(), //
        make_unique<ReadElectricalMeasurementAcVoltageOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcVoltageOverload>(), //
        make_unique<ReadElectricalMeasurementAcCurrentOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcCurrentOverload>(), //
        make_unique<ReadElectricalMeasurementAcActivePowerOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcActivePowerOverload>(), //
        make_unique<ReadElectricalMeasurementAcReactivePowerOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcReactivePowerOverload>(), //
        make_unique<ReadElectricalMeasurementAverageRmsOverVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsOverVoltage>(), //
        make_unique<ReadElectricalMeasurementAverageRmsUnderVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltage>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeOverVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltage>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeUnderVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltage>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSag>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSag>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSwell>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSwell>(), //
        make_unique<ReadElectricalMeasurementLineCurrentPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementLineCurrentPhaseB>(), //
        make_unique<ReadElectricalMeasurementActiveCurrentPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActiveCurrentPhaseB>(), //
        make_unique<ReadElectricalMeasurementReactiveCurrentPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsVoltagePhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltagePhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMinPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMaxPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMinPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMaxPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseB>(), //
        make_unique<ReadElectricalMeasurementActivePowerPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerPhaseB>(), //
        make_unique<ReadElectricalMeasurementActivePowerMinPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMinPhaseB>(), //
        make_unique<ReadElectricalMeasurementActivePowerMaxPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseB>(), //
        make_unique<ReadElectricalMeasurementReactivePowerPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementReactivePowerPhaseB>(), //
        make_unique<ReadElectricalMeasurementApparentPowerPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementApparentPowerPhaseB>(), //
        make_unique<ReadElectricalMeasurementPowerFactorPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPowerFactorPhaseB>(), //
        make_unique<ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB>(), //
        make_unique<ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseB>(), //
        make_unique<ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSagPeriodPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseB>(), //
        make_unique<ReadElectricalMeasurementLineCurrentPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementLineCurrentPhaseC>(), //
        make_unique<ReadElectricalMeasurementActiveCurrentPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActiveCurrentPhaseC>(), //
        make_unique<ReadElectricalMeasurementReactiveCurrentPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsVoltagePhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltagePhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMinPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMaxPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMinPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMaxPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseC>(), //
        make_unique<ReadElectricalMeasurementActivePowerPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerPhaseC>(), //
        make_unique<ReadElectricalMeasurementActivePowerMinPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMinPhaseC>(), //
        make_unique<ReadElectricalMeasurementActivePowerMaxPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseC>(), //
        make_unique<ReadElectricalMeasurementReactivePowerPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementReactivePowerPhaseC>(), //
        make_unique<ReadElectricalMeasurementApparentPowerPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementApparentPowerPhaseC>(), //
        make_unique<ReadElectricalMeasurementPowerFactorPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPowerFactorPhaseC>(), //
        make_unique<ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC>(), //
        make_unique<ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseC>(), //
        make_unique<ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSagPeriodPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseC>(), //
        make_unique<ReadElectricalMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeElectricalMeasurementGeneratedCommandList>(), //
        make_unique<ReadElectricalMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcceptedCommandList>(), //
        make_unique<ReadElectricalMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAttributeList>(), //
        make_unique<ReadElectricalMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeElectricalMeasurementFeatureMap>(), //
        make_unique<ReadElectricalMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeElectricalMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterTestCluster(Commands & commands)
{
    using namespace chip::app::Clusters::TestCluster;

    const char * clusterName = "TestCluster";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<TestClusterTest>(), //
        make_unique<TestClusterTestNotHandled>(), //
        make_unique<TestClusterTestSpecific>(), //
        make_unique<TestClusterTestUnknownCommand>(), //
        make_unique<TestClusterTestAddArguments>(), //
        make_unique<TestClusterTestSimpleArgumentRequest>(), //
        make_unique<TestClusterTestStructArrayArgumentRequest>(), //
        make_unique<TestClusterTestStructArgumentRequest>(), //
        make_unique<TestClusterTestNestedStructArgumentRequest>(), //
        make_unique<TestClusterTestListStructArgumentRequest>(), //
        make_unique<TestClusterTestListInt8UArgumentRequest>(), //
        make_unique<TestClusterTestNestedStructListArgumentRequest>(), //
        make_unique<TestClusterTestListNestedStructListArgumentRequest>(), //
        make_unique<TestClusterTestListInt8UReverseRequest>(), //
        make_unique<TestClusterTestEnumsRequest>(), //
        make_unique<TestClusterTestNullableOptionalRequest>(), //
        make_unique<TestClusterTestComplexNullableOptionalRequest>(), //
        make_unique<TestClusterSimpleStructEchoRequest>(), //
        make_unique<TestClusterTimedInvokeRequest>(), //
        make_unique<TestClusterTestSimpleOptionalArgumentRequest>(), //
        make_unique<TestClusterTestEmitTestEventRequest>(), //
        make_unique<TestClusterTestEmitTestFabricScopedEventRequest>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadTestClusterBoolean>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteTestClusterBoolean>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeTestClusterBoolean>(), //
        make_unique<ReadTestClusterBitmap8>(), //
        make_unique<WriteTestClusterBitmap8>(), //
        make_unique<SubscribeAttributeTestClusterBitmap8>(), //
        make_unique<ReadTestClusterBitmap16>(), //
        make_unique<WriteTestClusterBitmap16>(), //
        make_unique<SubscribeAttributeTestClusterBitmap16>(), //
        make_unique<ReadTestClusterBitmap32>(), //
        make_unique<WriteTestClusterBitmap32>(), //
        make_unique<SubscribeAttributeTestClusterBitmap32>(), //
        make_unique<ReadTestClusterBitmap64>(), //
        make_unique<WriteTestClusterBitmap64>(), //
        make_unique<SubscribeAttributeTestClusterBitmap64>(), //
        make_unique<ReadTestClusterInt8u>(), //
        make_unique<WriteTestClusterInt8u>(), //
        make_unique<SubscribeAttributeTestClusterInt8u>(), //
        make_unique<ReadTestClusterInt16u>(), //
        make_unique<WriteTestClusterInt16u>(), //
        make_unique<SubscribeAttributeTestClusterInt16u>(), //
        make_unique<ReadTestClusterInt24u>(), //
        make_unique<WriteTestClusterInt24u>(), //
        make_unique<SubscribeAttributeTestClusterInt24u>(), //
        make_unique<ReadTestClusterInt32u>(), //
        make_unique<WriteTestClusterInt32u>(), //
        make_unique<SubscribeAttributeTestClusterInt32u>(), //
        make_unique<ReadTestClusterInt40u>(), //
        make_unique<WriteTestClusterInt40u>(), //
        make_unique<SubscribeAttributeTestClusterInt40u>(), //
        make_unique<ReadTestClusterInt48u>(), //
        make_unique<WriteTestClusterInt48u>(), //
        make_unique<SubscribeAttributeTestClusterInt48u>(), //
        make_unique<ReadTestClusterInt56u>(), //
        make_unique<WriteTestClusterInt56u>(), //
        make_unique<SubscribeAttributeTestClusterInt56u>(), //
        make_unique<ReadTestClusterInt64u>(), //
        make_unique<WriteTestClusterInt64u>(), //
        make_unique<SubscribeAttributeTestClusterInt64u>(), //
        make_unique<ReadTestClusterInt8s>(), //
        make_unique<WriteTestClusterInt8s>(), //
        make_unique<SubscribeAttributeTestClusterInt8s>(), //
        make_unique<ReadTestClusterInt16s>(), //
        make_unique<WriteTestClusterInt16s>(), //
        make_unique<SubscribeAttributeTestClusterInt16s>(), //
        make_unique<ReadTestClusterInt24s>(), //
        make_unique<WriteTestClusterInt24s>(), //
        make_unique<SubscribeAttributeTestClusterInt24s>(), //
        make_unique<ReadTestClusterInt32s>(), //
        make_unique<WriteTestClusterInt32s>(), //
        make_unique<SubscribeAttributeTestClusterInt32s>(), //
        make_unique<ReadTestClusterInt40s>(), //
        make_unique<WriteTestClusterInt40s>(), //
        make_unique<SubscribeAttributeTestClusterInt40s>(), //
        make_unique<ReadTestClusterInt48s>(), //
        make_unique<WriteTestClusterInt48s>(), //
        make_unique<SubscribeAttributeTestClusterInt48s>(), //
        make_unique<ReadTestClusterInt56s>(), //
        make_unique<WriteTestClusterInt56s>(), //
        make_unique<SubscribeAttributeTestClusterInt56s>(), //
        make_unique<ReadTestClusterInt64s>(), //
        make_unique<WriteTestClusterInt64s>(), //
        make_unique<SubscribeAttributeTestClusterInt64s>(), //
        make_unique<ReadTestClusterEnum8>(), //
        make_unique<WriteTestClusterEnum8>(), //
        make_unique<SubscribeAttributeTestClusterEnum8>(), //
        make_unique<ReadTestClusterEnum16>(), //
        make_unique<WriteTestClusterEnum16>(), //
        make_unique<SubscribeAttributeTestClusterEnum16>(), //
        make_unique<ReadTestClusterFloatSingle>(), //
        make_unique<WriteTestClusterFloatSingle>(), //
        make_unique<SubscribeAttributeTestClusterFloatSingle>(), //
        make_unique<ReadTestClusterFloatDouble>(), //
        make_unique<WriteTestClusterFloatDouble>(), //
        make_unique<SubscribeAttributeTestClusterFloatDouble>(), //
        make_unique<ReadTestClusterOctetString>(), //
        make_unique<WriteTestClusterOctetString>(), //
        make_unique<SubscribeAttributeTestClusterOctetString>(), //
        make_unique<ReadTestClusterListInt8u>(), //
        make_unique<WriteTestClusterListInt8u>(), //
        make_unique<SubscribeAttributeTestClusterListInt8u>(), //
        make_unique<ReadTestClusterListOctetString>(), //
        make_unique<WriteTestClusterListOctetString>(), //
        make_unique<SubscribeAttributeTestClusterListOctetString>(), //
        make_unique<ReadTestClusterListStructOctetString>(), //
        make_unique<WriteTestClusterListStructOctetString>(), //
        make_unique<SubscribeAttributeTestClusterListStructOctetString>(), //
        make_unique<ReadTestClusterLongOctetString>(), //
        make_unique<WriteTestClusterLongOctetString>(), //
        make_unique<SubscribeAttributeTestClusterLongOctetString>(), //
        make_unique<ReadTestClusterCharString>(), //
        make_unique<WriteTestClusterCharString>(), //
        make_unique<SubscribeAttributeTestClusterCharString>(), //
        make_unique<ReadTestClusterLongCharString>(), //
        make_unique<WriteTestClusterLongCharString>(), //
        make_unique<SubscribeAttributeTestClusterLongCharString>(), //
        make_unique<ReadTestClusterEpochUs>(), //
        make_unique<WriteTestClusterEpochUs>(), //
        make_unique<SubscribeAttributeTestClusterEpochUs>(), //
        make_unique<ReadTestClusterEpochS>(), //
        make_unique<WriteTestClusterEpochS>(), //
        make_unique<SubscribeAttributeTestClusterEpochS>(), //
        make_unique<ReadTestClusterVendorId>(), //
        make_unique<WriteTestClusterVendorId>(), //
        make_unique<SubscribeAttributeTestClusterVendorId>(), //
        make_unique<ReadTestClusterListNullablesAndOptionalsStruct>(), //
        make_unique<WriteTestClusterListNullablesAndOptionalsStruct>(), //
        make_unique<SubscribeAttributeTestClusterListNullablesAndOptionalsStruct>(), //
        make_unique<ReadTestClusterEnumAttr>(), //
        make_unique<WriteTestClusterEnumAttr>(), //
        make_unique<SubscribeAttributeTestClusterEnumAttr>(), //
        make_unique<ReadTestClusterStructAttr>(), //
        make_unique<WriteTestClusterStructAttr>(), //
        make_unique<SubscribeAttributeTestClusterStructAttr>(), //
        make_unique<ReadTestClusterRangeRestrictedInt8u>(), //
        make_unique<WriteTestClusterRangeRestrictedInt8u>(), //
        make_unique<SubscribeAttributeTestClusterRangeRestrictedInt8u>(), //
        make_unique<ReadTestClusterRangeRestrictedInt8s>(), //
        make_unique<WriteTestClusterRangeRestrictedInt8s>(), //
        make_unique<SubscribeAttributeTestClusterRangeRestrictedInt8s>(), //
        make_unique<ReadTestClusterRangeRestrictedInt16u>(), //
        make_unique<WriteTestClusterRangeRestrictedInt16u>(), //
        make_unique<SubscribeAttributeTestClusterRangeRestrictedInt16u>(), //
        make_unique<ReadTestClusterRangeRestrictedInt16s>(), //
        make_unique<WriteTestClusterRangeRestrictedInt16s>(), //
        make_unique<SubscribeAttributeTestClusterRangeRestrictedInt16s>(), //
        make_unique<ReadTestClusterListLongOctetString>(), //
        make_unique<WriteTestClusterListLongOctetString>(), //
        make_unique<SubscribeAttributeTestClusterListLongOctetString>(), //
        make_unique<ReadTestClusterListFabricScoped>(), //
        make_unique<WriteTestClusterListFabricScoped>(), //
        make_unique<SubscribeAttributeTestClusterListFabricScoped>(), //
        make_unique<ReadTestClusterTimedWriteBoolean>(), //
        make_unique<WriteTestClusterTimedWriteBoolean>(), //
        make_unique<SubscribeAttributeTestClusterTimedWriteBoolean>(), //
        make_unique<ReadTestClusterGeneralErrorBoolean>(), //
        make_unique<WriteTestClusterGeneralErrorBoolean>(), //
        make_unique<SubscribeAttributeTestClusterGeneralErrorBoolean>(), //
        make_unique<ReadTestClusterClusterErrorBoolean>(), //
        make_unique<WriteTestClusterClusterErrorBoolean>(), //
        make_unique<SubscribeAttributeTestClusterClusterErrorBoolean>(), //
        make_unique<ReadTestClusterUnsupported>(), //
        make_unique<WriteTestClusterUnsupported>(), //
        make_unique<SubscribeAttributeTestClusterUnsupported>(), //
        make_unique<ReadTestClusterNullableBoolean>(), //
        make_unique<WriteTestClusterNullableBoolean>(), //
        make_unique<SubscribeAttributeTestClusterNullableBoolean>(), //
        make_unique<ReadTestClusterNullableBitmap8>(), //
        make_unique<WriteTestClusterNullableBitmap8>(), //
        make_unique<SubscribeAttributeTestClusterNullableBitmap8>(), //
        make_unique<ReadTestClusterNullableBitmap16>(), //
        make_unique<WriteTestClusterNullableBitmap16>(), //
        make_unique<SubscribeAttributeTestClusterNullableBitmap16>(), //
        make_unique<ReadTestClusterNullableBitmap32>(), //
        make_unique<WriteTestClusterNullableBitmap32>(), //
        make_unique<SubscribeAttributeTestClusterNullableBitmap32>(), //
        make_unique<ReadTestClusterNullableBitmap64>(), //
        make_unique<WriteTestClusterNullableBitmap64>(), //
        make_unique<SubscribeAttributeTestClusterNullableBitmap64>(), //
        make_unique<ReadTestClusterNullableInt8u>(), //
        make_unique<WriteTestClusterNullableInt8u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt8u>(), //
        make_unique<ReadTestClusterNullableInt16u>(), //
        make_unique<WriteTestClusterNullableInt16u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt16u>(), //
        make_unique<ReadTestClusterNullableInt24u>(), //
        make_unique<WriteTestClusterNullableInt24u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt24u>(), //
        make_unique<ReadTestClusterNullableInt32u>(), //
        make_unique<WriteTestClusterNullableInt32u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt32u>(), //
        make_unique<ReadTestClusterNullableInt40u>(), //
        make_unique<WriteTestClusterNullableInt40u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt40u>(), //
        make_unique<ReadTestClusterNullableInt48u>(), //
        make_unique<WriteTestClusterNullableInt48u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt48u>(), //
        make_unique<ReadTestClusterNullableInt56u>(), //
        make_unique<WriteTestClusterNullableInt56u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt56u>(), //
        make_unique<ReadTestClusterNullableInt64u>(), //
        make_unique<WriteTestClusterNullableInt64u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt64u>(), //
        make_unique<ReadTestClusterNullableInt8s>(), //
        make_unique<WriteTestClusterNullableInt8s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt8s>(), //
        make_unique<ReadTestClusterNullableInt16s>(), //
        make_unique<WriteTestClusterNullableInt16s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt16s>(), //
        make_unique<ReadTestClusterNullableInt24s>(), //
        make_unique<WriteTestClusterNullableInt24s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt24s>(), //
        make_unique<ReadTestClusterNullableInt32s>(), //
        make_unique<WriteTestClusterNullableInt32s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt32s>(), //
        make_unique<ReadTestClusterNullableInt40s>(), //
        make_unique<WriteTestClusterNullableInt40s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt40s>(), //
        make_unique<ReadTestClusterNullableInt48s>(), //
        make_unique<WriteTestClusterNullableInt48s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt48s>(), //
        make_unique<ReadTestClusterNullableInt56s>(), //
        make_unique<WriteTestClusterNullableInt56s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt56s>(), //
        make_unique<ReadTestClusterNullableInt64s>(), //
        make_unique<WriteTestClusterNullableInt64s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt64s>(), //
        make_unique<ReadTestClusterNullableEnum8>(), //
        make_unique<WriteTestClusterNullableEnum8>(), //
        make_unique<SubscribeAttributeTestClusterNullableEnum8>(), //
        make_unique<ReadTestClusterNullableEnum16>(), //
        make_unique<WriteTestClusterNullableEnum16>(), //
        make_unique<SubscribeAttributeTestClusterNullableEnum16>(), //
        make_unique<ReadTestClusterNullableFloatSingle>(), //
        make_unique<WriteTestClusterNullableFloatSingle>(), //
        make_unique<SubscribeAttributeTestClusterNullableFloatSingle>(), //
        make_unique<ReadTestClusterNullableFloatDouble>(), //
        make_unique<WriteTestClusterNullableFloatDouble>(), //
        make_unique<SubscribeAttributeTestClusterNullableFloatDouble>(), //
        make_unique<ReadTestClusterNullableOctetString>(), //
        make_unique<WriteTestClusterNullableOctetString>(), //
        make_unique<SubscribeAttributeTestClusterNullableOctetString>(), //
        make_unique<ReadTestClusterNullableCharString>(), //
        make_unique<WriteTestClusterNullableCharString>(), //
        make_unique<SubscribeAttributeTestClusterNullableCharString>(), //
        make_unique<ReadTestClusterNullableEnumAttr>(), //
        make_unique<WriteTestClusterNullableEnumAttr>(), //
        make_unique<SubscribeAttributeTestClusterNullableEnumAttr>(), //
        make_unique<ReadTestClusterNullableStruct>(), //
        make_unique<WriteTestClusterNullableStruct>(), //
        make_unique<SubscribeAttributeTestClusterNullableStruct>(), //
        make_unique<ReadTestClusterNullableRangeRestrictedInt8u>(), //
        make_unique<WriteTestClusterNullableRangeRestrictedInt8u>(), //
        make_unique<SubscribeAttributeTestClusterNullableRangeRestrictedInt8u>(), //
        make_unique<ReadTestClusterNullableRangeRestrictedInt8s>(), //
        make_unique<WriteTestClusterNullableRangeRestrictedInt8s>(), //
        make_unique<SubscribeAttributeTestClusterNullableRangeRestrictedInt8s>(), //
        make_unique<ReadTestClusterNullableRangeRestrictedInt16u>(), //
        make_unique<WriteTestClusterNullableRangeRestrictedInt16u>(), //
        make_unique<SubscribeAttributeTestClusterNullableRangeRestrictedInt16u>(), //
        make_unique<ReadTestClusterNullableRangeRestrictedInt16s>(), //
        make_unique<WriteTestClusterNullableRangeRestrictedInt16s>(), //
        make_unique<SubscribeAttributeTestClusterNullableRangeRestrictedInt16s>(), //
        make_unique<ReadTestClusterGeneratedCommandList>(), //
        make_unique<SubscribeAttributeTestClusterGeneratedCommandList>(), //
        make_unique<ReadTestClusterAcceptedCommandList>(), //
        make_unique<SubscribeAttributeTestClusterAcceptedCommandList>(), //
        make_unique<ReadTestClusterAttributeList>(), //
        make_unique<SubscribeAttributeTestClusterAttributeList>(), //
        make_unique<ReadTestClusterFeatureMap>(), //
        make_unique<SubscribeAttributeTestClusterFeatureMap>(), //
        make_unique<ReadTestClusterClusterRevision>(), //
        make_unique<SubscribeAttributeTestClusterClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}

void registerClusterAny(Commands & commands)
{
    const char * clusterName = "Any";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(), //
        make_unique<ReadAttribute>(), //
        make_unique<WriteAttribute>(), //
        make_unique<SubscribeAttribute>(), //
        make_unique<SubscribeEvent>(), //
    };

    commands.Register(clusterName, clusterCommands);
}

void registerClusters(Commands & commands)
{
    registerClusterAny(commands);
    registerClusterIdentify(commands);
    registerClusterGroups(commands);
    registerClusterScenes(commands);
    registerClusterOnOff(commands);
    registerClusterOnOffSwitchConfiguration(commands);
    registerClusterLevelControl(commands);
    registerClusterBinaryInputBasic(commands);
    registerClusterDescriptor(commands);
    registerClusterBinding(commands);
    registerClusterAccessControl(commands);
    registerClusterBridgedActions(commands);
    registerClusterBasic(commands);
    registerClusterOtaSoftwareUpdateProvider(commands);
    registerClusterOtaSoftwareUpdateRequestor(commands);
    registerClusterLocalizationConfiguration(commands);
    registerClusterTimeFormatLocalization(commands);
    registerClusterUnitLocalization(commands);
    registerClusterPowerSourceConfiguration(commands);
    registerClusterPowerSource(commands);
    registerClusterGeneralCommissioning(commands);
    registerClusterNetworkCommissioning(commands);
    registerClusterDiagnosticLogs(commands);
    registerClusterGeneralDiagnostics(commands);
    registerClusterSoftwareDiagnostics(commands);
    registerClusterThreadNetworkDiagnostics(commands);
    registerClusterWiFiNetworkDiagnostics(commands);
    registerClusterEthernetNetworkDiagnostics(commands);
    registerClusterBridgedDeviceBasic(commands);
    registerClusterSwitch(commands);
    registerClusterAdministratorCommissioning(commands);
    registerClusterOperationalCredentials(commands);
    registerClusterGroupKeyManagement(commands);
    registerClusterFixedLabel(commands);
    registerClusterUserLabel(commands);
    registerClusterBooleanState(commands);
    registerClusterModeSelect(commands);
    registerClusterDoorLock(commands);
    registerClusterWindowCovering(commands);
    registerClusterBarrierControl(commands);
    registerClusterPumpConfigurationAndControl(commands);
    registerClusterThermostat(commands);
    registerClusterFanControl(commands);
    registerClusterThermostatUserInterfaceConfiguration(commands);
    registerClusterColorControl(commands);
    registerClusterBallastConfiguration(commands);
    registerClusterIlluminanceMeasurement(commands);
    registerClusterTemperatureMeasurement(commands);
    registerClusterPressureMeasurement(commands);
    registerClusterFlowMeasurement(commands);
    registerClusterRelativeHumidityMeasurement(commands);
    registerClusterOccupancySensing(commands);
    registerClusterWakeOnLan(commands);
    registerClusterChannel(commands);
    registerClusterTargetNavigator(commands);
    registerClusterMediaPlayback(commands);
    registerClusterMediaInput(commands);
    registerClusterLowPower(commands);
    registerClusterKeypadInput(commands);
    registerClusterContentLauncher(commands);
    registerClusterAudioOutput(commands);
    registerClusterApplicationLauncher(commands);
    registerClusterApplicationBasic(commands);
    registerClusterAccountLogin(commands);
    registerClusterElectricalMeasurement(commands);
    registerClusterTestCluster(commands);
}
