Clearly distinguish between unknown and all-0 discovery capabilities. (#21696)

SetUpCodePairer was treating all-0 as unknown, which is not really right.
diff --git a/examples/all-clusters-app/nxp/mw320/main.cpp b/examples/all-clusters-app/nxp/mw320/main.cpp
index 52fbb40..94ed17d 100644
--- a/examples/all-clusters-app/nxp/mw320/main.cpp
+++ b/examples/all-clusters-app/nxp/mw320/main.cpp
@@ -775,7 +775,7 @@
     payload.version               = 0;
     payload.discriminator         = discriminator;
     payload.setUpPINCode          = setupPINCode;
-    payload.rendezvousInformation = RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE);
+    payload.rendezvousInformation.SetValue(chip::RendezvousInformationFlag::kBLE);
     payload.vendorID              = vendorId;
     payload.productID             = productId;
 
diff --git a/examples/chip-tool/commands/payload/SetupPayloadGenerateCommand.cpp b/examples/chip-tool/commands/payload/SetupPayloadGenerateCommand.cpp
index f95932f..b873c15 100644
--- a/examples/chip-tool/commands/payload/SetupPayloadGenerateCommand.cpp
+++ b/examples/chip-tool/commands/payload/SetupPayloadGenerateCommand.cpp
@@ -77,7 +77,12 @@
 
     if (mRendezvous.HasValue())
     {
-        payload.rendezvousInformation.SetRaw(mRendezvous.Value());
+        payload.rendezvousInformation.Emplace().SetRaw(mRendezvous.Value());
+    }
+    else if (!payload.rendezvousInformation.HasValue())
+    {
+        // Default to not having anything in the discovery capabilities.
+        payload.rendezvousInformation.SetValue(RendezvousInformationFlag::kNone);
     }
 
     if (mTLVBytes.HasValue())
diff --git a/examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp b/examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp
index d76b6f5..1bec630 100644
--- a/examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp
+++ b/examples/chip-tool/commands/payload/SetupPayloadParseCommand.cpp
@@ -78,35 +78,43 @@
     {
         StringBuilder<128> humanFlags;
 
-        if (payload.rendezvousInformation.HasAny())
+        if (!payload.rendezvousInformation.HasValue())
         {
-            if (payload.rendezvousInformation.Has(RendezvousInformationFlag::kSoftAP))
-            {
-                humanFlags.Add("Soft-AP");
-            }
-            if (payload.rendezvousInformation.Has(RendezvousInformationFlag::kBLE))
-            {
-                if (!humanFlags.Empty())
-                {
-                    humanFlags.Add(", ");
-                }
-                humanFlags.Add("BLE");
-            }
-            if (payload.rendezvousInformation.Has(RendezvousInformationFlag::kOnNetwork))
-            {
-                if (!humanFlags.Empty())
-                {
-                    humanFlags.Add(", ");
-                }
-                humanFlags.Add("On IP network");
-            }
+            ChipLogProgress(SetupPayload, "Discovery Bitmask:   UNKNOWN");
         }
         else
         {
-            humanFlags.Add("NONE");
-        }
+            if (payload.rendezvousInformation.Value().HasAny())
+            {
+                if (payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kSoftAP))
+                {
+                    humanFlags.Add("Soft-AP");
+                }
+                if (payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kBLE))
+                {
+                    if (!humanFlags.Empty())
+                    {
+                        humanFlags.Add(", ");
+                    }
+                    humanFlags.Add("BLE");
+                }
+                if (payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kOnNetwork))
+                {
+                    if (!humanFlags.Empty())
+                    {
+                        humanFlags.Add(", ");
+                    }
+                    humanFlags.Add("On IP network");
+                }
+            }
+            else
+            {
+                humanFlags.Add("NONE");
+            }
 
-        ChipLogProgress(SetupPayload, "Capabilities:        0x%02X (%s)", payload.rendezvousInformation.Raw(), humanFlags.c_str());
+            ChipLogProgress(SetupPayload, "Discovery Bitmask:   0x%02X (%s)", payload.rendezvousInformation.Value().Raw(),
+                            humanFlags.c_str());
+        }
     }
     if (payload.discriminator.IsShortDiscriminator())
     {
diff --git a/examples/darwin-framework-tool/commands/payload/SetupPayloadParseCommand.mm b/examples/darwin-framework-tool/commands/payload/SetupPayloadParseCommand.mm
index 1cd479c..9cb8aba 100644
--- a/examples/darwin-framework-tool/commands/payload/SetupPayloadParseCommand.mm
+++ b/examples/darwin-framework-tool/commands/payload/SetupPayloadParseCommand.mm
@@ -84,33 +84,34 @@
     NSLog(@"ProductID:     %@", payload.productID);
     NSLog(@"Custom flow:   %lu    (%@)", payload.commissioningFlow, CustomFlowString(payload.commissioningFlow));
     {
-        NSMutableString * humanFlags = [[NSMutableString alloc] init];
+        if (payload.rendezvousInformation == nil) {
+            NSLog(@"Capabilities:  UNKNOWN");
+        } else {
+            NSMutableString * humanFlags = [[NSMutableString alloc] init];
 
-        if (payload.rendezvousInformation) {
-            if (payload.rendezvousInformation & MTRRendezvousInformationNone) {
+            auto value = [payload.rendezvousInformation unsignedLongValue];
+            if (value == MTRDiscoveryCapabilitiesNone) {
                 [humanFlags appendString:@"NONE"];
             } else {
-                if (payload.rendezvousInformation & MTRRendezvousInformationSoftAP) {
+                if (value & MTRDiscoveryCapabilitiesSoftAP) {
                     [humanFlags appendString:@"SoftAP"];
                 }
-                if (payload.rendezvousInformation & MTRRendezvousInformationBLE) {
+                if (value & MTRDiscoveryCapabilitiesBLE) {
                     if (!humanFlags) {
                         [humanFlags appendString:@", "];
                     }
                     [humanFlags appendString:@"BLE"];
                 }
-                if (payload.rendezvousInformation & MTRRendezvousInformationOnNetwork) {
+                if (value & MTRDiscoveryCapabilitiesOnNetwork) {
                     if (!humanFlags) {
                         [humanFlags appendString:@", "];
                     }
                     [humanFlags appendString:@"ON NETWORK"];
                 }
             }
-        } else {
-            [humanFlags appendString:@"NONE"];
-        }
 
-        NSLog(@"Capabilities:  0x%02lX (%@)", payload.rendezvousInformation, humanFlags);
+            NSLog(@"Capabilities:  0x%02lX (%@)", value, humanFlags);
+        }
     }
     NSLog(@"Discriminator: %@", payload.discriminator);
     NSLog(@"Passcode:      %@", payload.setUpPINCode);
diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp
index 052000f..8afd89d 100644
--- a/examples/platform/linux/AppMain.cpp
+++ b/examples/platform/linux/AppMain.cpp
@@ -186,9 +186,9 @@
                                                    LinuxDeviceOptions::GetInstance());
     SuccessOrExit(err);
 
-    if (LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.HasAny())
+    if (LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.HasValue())
     {
-        rendezvousFlags = LinuxDeviceOptions::GetInstance().payload.rendezvousInformation;
+        rendezvousFlags = LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.Value();
     }
 
     err = GetPayloadContents(LinuxDeviceOptions::GetInstance().payload, rendezvousFlags);
diff --git a/examples/platform/linux/Options.cpp b/examples/platform/linux/Options.cpp
index f1b1d6c..73fe356 100644
--- a/examples/platform/linux/Options.cpp
+++ b/examples/platform/linux/Options.cpp
@@ -283,7 +283,7 @@
         break;
 
     case kDeviceOption_Capabilities:
-        LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.SetRaw(static_cast<uint8_t>(atoi(aValue)));
+        LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.Emplace().SetRaw(static_cast<uint8_t>(atoi(aValue)));
         break;
 
     case kDeviceOption_Discriminator: {
diff --git a/src/app/server/OnboardingCodesUtil.cpp b/src/app/server/OnboardingCodesUtil.cpp
index 72d1a9d..44c5e35 100644
--- a/src/app/server/OnboardingCodesUtil.cpp
+++ b/src/app/server/OnboardingCodesUtil.cpp
@@ -98,9 +98,9 @@
 
 CHIP_ERROR GetPayloadContents(chip::PayloadContents & aPayload, chip::RendezvousInformationFlags aRendezvousFlags)
 {
-    CHIP_ERROR err                 = CHIP_NO_ERROR;
-    aPayload.version               = 0;
-    aPayload.rendezvousInformation = aRendezvousFlags;
+    CHIP_ERROR err   = CHIP_NO_ERROR;
+    aPayload.version = 0;
+    aPayload.rendezvousInformation.SetValue(aRendezvousFlags);
 
     err = GetCommissionableDataProvider()->GetSetupPasscode(aPayload.setUpPINCode);
     if (err != CHIP_NO_ERROR)
diff --git a/src/controller/CommissioningWindowOpener.cpp b/src/controller/CommissioningWindowOpener.cpp
index 9afe3d1..c9fd138 100644
--- a/src/controller/CommissioningWindowOpener.cpp
+++ b/src/controller/CommissioningWindowOpener.cpp
@@ -98,7 +98,7 @@
 
     mSetupPayload.version = 0;
     mSetupPayload.discriminator.SetLongValue(discriminator);
-    mSetupPayload.rendezvousInformation = RendezvousInformationFlags(RendezvousInformationFlag::kOnNetwork);
+    mSetupPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kOnNetwork);
 
     mCommissioningWindowCallback      = callback;
     mBasicCommissioningWindowCallback = nullptr;
diff --git a/src/controller/SetUpCodePairer.cpp b/src/controller/SetUpCodePairer.cpp
index 0e72dda..c24ecc5 100644
--- a/src/controller/SetUpCodePairer.cpp
+++ b/src/controller/SetUpCodePairer.cpp
@@ -71,8 +71,8 @@
     CHIP_ERROR err = CHIP_NO_ERROR;
     bool isRunning = false;
 
-    bool searchOverAll = payload.rendezvousInformation == RendezvousInformationFlag::kNone;
-    if (searchOverAll || payload.rendezvousInformation == RendezvousInformationFlag::kBLE)
+    bool searchOverAll = !payload.rendezvousInformation.HasValue();
+    if (searchOverAll || payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kBLE))
     {
         if (CHIP_NO_ERROR == (err = StartDiscoverOverBle(payload)))
         {
@@ -81,7 +81,7 @@
         VerifyOrReturnError(searchOverAll || CHIP_NO_ERROR == err || CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE == err, err);
     }
 
-    if (searchOverAll || payload.rendezvousInformation == RendezvousInformationFlag::kSoftAP)
+    if (searchOverAll || payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kSoftAP))
     {
         if (CHIP_NO_ERROR == (err = StartDiscoverOverSoftAP(payload)))
         {
diff --git a/src/controller/python/chip/setup_payload/Generator.cpp b/src/controller/python/chip/setup_payload/Generator.cpp
index 8037689..4211fc3 100644
--- a/src/controller/python/chip/setup_payload/Generator.cpp
+++ b/src/controller/python/chip/setup_payload/Generator.cpp
@@ -40,7 +40,7 @@
     payload.vendorID     = vendorId;
     payload.productID    = productId;
     payload.discriminator.SetLongValue(discriminator);
-    payload.rendezvousInformation = rendezvousFlags.SetRaw(capabilities);
+    payload.rendezvousInformation.SetValue(rendezvousFlags.SetRaw(capabilities));
 
     switch (customFlow)
     {
diff --git a/src/controller/python/chip/setup_payload/Parser.cpp b/src/controller/python/chip/setup_payload/Parser.cpp
index 29b5ec1..83266f1 100644
--- a/src/controller/python/chip/setup_payload/Parser.cpp
+++ b/src/controller/python/chip/setup_payload/Parser.cpp
@@ -38,7 +38,10 @@
     attrVisitor("VendorID", std::to_string(payload.vendorID).c_str());
     attrVisitor("ProductID", std::to_string(payload.productID).c_str());
     attrVisitor("CommissioningFlow", std::to_string(static_cast<uint8_t>(payload.commissioningFlow)).c_str());
-    attrVisitor("RendezvousInformation", std::to_string(payload.rendezvousInformation.Raw()).c_str());
+    if (payload.rendezvousInformation.HasValue())
+    {
+        attrVisitor("RendezvousInformation", std::to_string(payload.rendezvousInformation.Value().Raw()).c_str());
+    }
     if (payload.discriminator.IsShortDiscriminator())
     {
         attrVisitor("Short discriminator", std::to_string(payload.discriminator.GetShortValue()).c_str());
diff --git a/src/darwin/CHIPTool/CHIPTool/View Controllers/QRCode/QRCodeViewController.m b/src/darwin/CHIPTool/CHIPTool/View Controllers/QRCode/QRCodeViewController.m
index 0d8da17..e31e52b 100644
--- a/src/darwin/CHIPTool/CHIPTool/View Controllers/QRCode/QRCodeViewController.m
+++ b/src/darwin/CHIPTool/CHIPTool/View Controllers/QRCode/QRCodeViewController.m
@@ -706,7 +706,11 @@
     } else {
         _manualCodeLabel.hidden = YES;
         _versionLabel.text = [NSString stringWithFormat:@"%@", payload.version];
-        _rendezVousInformation.text = [NSString stringWithFormat:@"%lu", payload.rendezvousInformation];
+        if (payload.rendezvousInformation == nil) {
+            _rendezVousInformation.text = NOT_APPLICABLE_STRING;
+        } else {
+            _rendezVousInformation.text = [NSString stringWithFormat:@"%lu", [payload.rendezvousInformation unsignedLongValue]];
+        }
         if ([payload.serialNumber length] > 0) {
             self->_serialNumber.text = payload.serialNumber;
         } else {
@@ -763,15 +767,22 @@
 
 - (void)handleRendezVous:(MTRSetupPayload *)payload rawPayload:(NSString *)rawPayload
 {
-    switch (payload.rendezvousInformation) {
-    case MTRRendezvousInformationNone:
-    case MTRRendezvousInformationOnNetwork:
-    case MTRRendezvousInformationBLE:
-    case MTRRendezvousInformationAllMask:
+    if (payload.rendezvousInformation == nil) {
+        NSLog(@"Rendezvous Default");
+        [self handleRendezVousDefault:rawPayload];
+        return;
+    }
+
+    // TODO: This is a pretty broken way to handle a bitmask.
+    switch ([payload.rendezvousInformation unsignedLongValue]) {
+    case MTRDiscoveryCapabilitiesNone:
+    case MTRDiscoveryCapabilitiesOnNetwork:
+    case MTRDiscoveryCapabilitiesBLE:
+    case MTRDiscoveryCapabilitiesAllMask:
         NSLog(@"Rendezvous Default");
         [self handleRendezVousDefault:rawPayload];
         break;
-    case MTRRendezvousInformationSoftAP:
+    case MTRDiscoveryCapabilitiesSoftAP:
         NSLog(@"Rendezvous Wi-Fi");
         [self handleRendezVousWiFi:[self getNetworkName:payload.discriminator]];
         break;
diff --git a/src/darwin/Framework/CHIP/MTRSetupPayload.h b/src/darwin/Framework/CHIP/MTRSetupPayload.h
index 4f0b02a..73fd981 100644
--- a/src/darwin/Framework/CHIP/MTRSetupPayload.h
+++ b/src/darwin/Framework/CHIP/MTRSetupPayload.h
@@ -19,14 +19,14 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
-typedef NS_ENUM(NSUInteger, MTRRendezvousInformationFlags) {
-    MTRRendezvousInformationNone = 0, // Device does not support any method for rendezvous
-    MTRRendezvousInformationSoftAP = 1 << 0, // Device supports WiFi softAP
-    MTRRendezvousInformationBLE = 1 << 1, // Device supports BLE
-    MTRRendezvousInformationOnNetwork = 1 << 2, // Device supports On Network setup
+typedef NS_ENUM(NSUInteger, MTRDiscoveryCapabilities) {
+    MTRDiscoveryCapabilitiesNone = 0, // Device does not support any method for rendezvous
+    MTRDiscoveryCapabilitiesSoftAP = 1 << 0, // Device supports WiFi softAP
+    MTRDiscoveryCapabilitiesBLE = 1 << 1, // Device supports BLE
+    MTRDiscoveryCapabilitiesOnNetwork = 1 << 2, // Device supports On Network setup
 
-    MTRRendezvousInformationAllMask
-    = MTRRendezvousInformationSoftAP | MTRRendezvousInformationBLE | MTRRendezvousInformationOnNetwork,
+    MTRDiscoveryCapabilitiesAllMask
+    = MTRDiscoveryCapabilitiesSoftAP | MTRDiscoveryCapabilitiesBLE | MTRDiscoveryCapabilitiesOnNetwork,
 };
 
 typedef NS_ENUM(NSUInteger, MTRCommissioningFlow) {
@@ -55,7 +55,13 @@
 @property (nonatomic, copy) NSNumber * vendorID;
 @property (nonatomic, copy) NSNumber * productID;
 @property (nonatomic, assign) MTRCommissioningFlow commissioningFlow;
-@property (nonatomic, assign) MTRRendezvousInformationFlags rendezvousInformation;
+/**
+ * rendezvousInformation is nil when the discovery capabilities bitmask is
+ * unknown.
+ *
+ * Otherwise its value is made up of the MTRDiscoveryCapabilities flags.
+ */
+@property (nonatomic, assign, nullable) NSNumber * rendezvousInformation;
 @property (nonatomic, copy) NSNumber * discriminator;
 @property (nonatomic, assign) BOOL hasShortDiscriminator;
 @property (nonatomic, copy) NSNumber * setUpPINCode;
diff --git a/src/darwin/Framework/CHIP/MTRSetupPayload.mm b/src/darwin/Framework/CHIP/MTRSetupPayload.mm
index 7b96386..17f1696 100644
--- a/src/darwin/Framework/CHIP/MTRSetupPayload.mm
+++ b/src/darwin/Framework/CHIP/MTRSetupPayload.mm
@@ -27,18 +27,23 @@
     chip::SetupPayload _chipSetupPayload;
 }
 
-- (MTRRendezvousInformationFlags)convertRendezvousFlags:(chip::RendezvousInformationFlags)value
+- (NSNumber *)convertRendezvousFlags:(const chip::Optional<chip::RendezvousInformationFlags> &)value
 {
-    if (value.Has(chip::RendezvousInformationFlag::kBLE)) {
-        return MTRRendezvousInformationBLE;
+    if (!value.HasValue()) {
+        return nil;
     }
-    if (value.Has(chip::RendezvousInformationFlag::kSoftAP)) {
-        return MTRRendezvousInformationSoftAP;
+
+    NSUInteger flags = MTRDiscoveryCapabilitiesNone;
+    if (value.Value().Has(chip::RendezvousInformationFlag::kBLE)) {
+        flags |= MTRDiscoveryCapabilitiesBLE;
     }
-    if (value.Has(chip::RendezvousInformationFlag::kOnNetwork)) {
-        return MTRRendezvousInformationOnNetwork;
+    if (value.Value().Has(chip::RendezvousInformationFlag::kSoftAP)) {
+        flags |= MTRDiscoveryCapabilitiesSoftAP;
     }
-    return MTRRendezvousInformationNone;
+    if (value.Value().Has(chip::RendezvousInformationFlag::kOnNetwork)) {
+        flags |= MTRDiscoveryCapabilitiesOnNetwork;
+    }
+    return [NSNumber numberWithUnsignedLong:flags];
 }
 
 - (MTRCommissioningFlow)convertCommissioningFlow:(chip::CommissioningFlow)value
@@ -154,10 +159,10 @@
     [coder encodeObject:self.version forKey:MTRSetupPayloadCodingKeyVersion];
     [coder encodeObject:self.vendorID forKey:MTRSetupPayloadCodingKeyVendorID];
     [coder encodeObject:self.productID forKey:MTRSetupPayloadCodingKeyProductID];
-    // Casts are safe because commissioning flow, rendezvous information, and
-    // hasShortDiscriminator values are all pretty small and non-negative.
+    // Casts are safe because commissioning flow and hasShortDiscriminator
+    // values are both pretty small and non-negative.
     [coder encodeInteger:static_cast<NSInteger>(self.commissioningFlow) forKey:MTRSetupPayloadCodingKeyCommissioningFlow];
-    [coder encodeInteger:static_cast<NSInteger>(self.rendezvousInformation) forKey:MTRSetupPayloadCodingKeyRendezvousFlags];
+    [coder encodeObject:self.rendezvousInformation forKey:MTRSetupPayloadCodingKeyRendezvousFlags];
     [coder encodeInteger:static_cast<NSInteger>(self.hasShortDiscriminator) forKey:MTRSetupPayloadCodingKeyHasShortDiscriminator];
     [coder encodeObject:self.discriminator forKey:MTRSetupPayloadCodingKeyDiscriminator];
     [coder encodeObject:self.setUpPINCode forKey:MTRSetupPayloadCodingKeySetupPINCode];
@@ -170,7 +175,8 @@
     NSNumber * vendorID = [decoder decodeObjectOfClass:[NSNumber class] forKey:MTRSetupPayloadCodingKeyVendorID];
     NSNumber * productID = [decoder decodeObjectOfClass:[NSNumber class] forKey:MTRSetupPayloadCodingKeyProductID];
     NSInteger commissioningFlow = [decoder decodeIntegerForKey:MTRSetupPayloadCodingKeyCommissioningFlow];
-    NSInteger rendezvousInformation = [decoder decodeIntegerForKey:MTRSetupPayloadCodingKeyRendezvousFlags];
+    NSNumber * rendezvousInformation = [decoder decodeObjectOfClass:[NSNumber class]
+                                                             forKey:MTRSetupPayloadCodingKeyRendezvousFlags];
     NSInteger hasShortDiscriminator = [decoder decodeIntegerForKey:MTRSetupPayloadCodingKeyHasShortDiscriminator];
     NSNumber * discriminator = [decoder decodeObjectOfClass:[NSNumber class] forKey:MTRSetupPayloadCodingKeyDiscriminator];
     NSNumber * setUpPINCode = [decoder decodeObjectOfClass:[NSNumber class] forKey:MTRSetupPayloadCodingKeySetupPINCode];
@@ -181,7 +187,7 @@
     payload.vendorID = vendorID;
     payload.productID = productID;
     payload.commissioningFlow = static_cast<MTRCommissioningFlow>(commissioningFlow);
-    payload.rendezvousInformation = static_cast<MTRRendezvousInformationFlags>(rendezvousInformation);
+    payload.rendezvousInformation = rendezvousInformation;
     payload.hasShortDiscriminator = static_cast<BOOL>(hasShortDiscriminator);
     payload.discriminator = discriminator;
     payload.setUpPINCode = setUpPINCode;
diff --git a/src/darwin/Framework/CHIP/MTRSetupPayload_Internal.h b/src/darwin/Framework/CHIP/MTRSetupPayload_Internal.h
index afe3c08..88a4d83 100644
--- a/src/darwin/Framework/CHIP/MTRSetupPayload_Internal.h
+++ b/src/darwin/Framework/CHIP/MTRSetupPayload_Internal.h
@@ -10,6 +10,7 @@
 #import "MTRSetupPayload.h"
 
 #ifdef __cplusplus
+#import <lib/core/Optional.h>
 #import <setup_payload/SetupPayload.h>
 #endif
 
@@ -17,7 +18,7 @@
 
 #ifdef __cplusplus
 - (id)initWithSetupPayload:(chip::SetupPayload)setupPayload;
-- (MTRRendezvousInformationFlags)convertRendezvousFlags:(chip::RendezvousInformationFlags)value;
+- (NSNumber *)convertRendezvousFlags:(const chip::Optional<chip::RendezvousInformationFlags> &)value;
 - (MTRCommissioningFlow)convertCommissioningFlow:(chip::CommissioningFlow)value;
 #endif
 
diff --git a/src/darwin/Framework/CHIPTests/MTRSetupPayloadParserTests.m b/src/darwin/Framework/CHIPTests/MTRSetupPayloadParserTests.m
index 4c043b7..aae5f60 100644
--- a/src/darwin/Framework/CHIPTests/MTRSetupPayloadParserTests.m
+++ b/src/darwin/Framework/CHIPTests/MTRSetupPayloadParserTests.m
@@ -52,7 +52,7 @@
     XCTAssertEqual(payload.productID.unsignedIntegerValue, 1);
     XCTAssertEqual(payload.commissioningFlow, MTRCommissioningFlowCustom);
     XCTAssertEqual(payload.version.unsignedIntegerValue, 0);
-    XCTAssertEqual(payload.rendezvousInformation, MTRRendezvousInformationNone);
+    XCTAssertNil(payload.rendezvousInformation);
 }
 
 - (void)testOnboardingPayloadParser_Manual_WrongType
@@ -83,7 +83,7 @@
     XCTAssertEqual(payload.productID.unsignedIntegerValue, 1);
     XCTAssertEqual(payload.commissioningFlow, MTRCommissioningFlowCustom);
     XCTAssertEqual(payload.version.unsignedIntegerValue, 0);
-    XCTAssertEqual(payload.rendezvousInformation, MTRRendezvousInformationNone);
+    XCTAssertNil(payload.rendezvousInformation);
 }
 
 - (void)testOnboardingPayloadParser_Admin_WrongType
@@ -114,7 +114,8 @@
     XCTAssertEqual(payload.productID.unsignedIntegerValue, 1);
     XCTAssertEqual(payload.commissioningFlow, MTRCommissioningFlowStandard);
     XCTAssertEqual(payload.version.unsignedIntegerValue, 5);
-    XCTAssertEqual(payload.rendezvousInformation, MTRRendezvousInformationSoftAP);
+    XCTAssertNotNil(payload.rendezvousInformation);
+    XCTAssertEqual([payload.rendezvousInformation unsignedLongValue], MTRDiscoveryCapabilitiesSoftAP);
 }
 
 - (void)testOnboardingPayloadParser_QRCode_WrongType
@@ -146,7 +147,8 @@
     XCTAssertEqual(payload.productID.unsignedIntegerValue, 1);
     XCTAssertEqual(payload.commissioningFlow, MTRCommissioningFlowStandard);
     XCTAssertEqual(payload.version.unsignedIntegerValue, 5);
-    XCTAssertEqual(payload.rendezvousInformation, MTRRendezvousInformationSoftAP);
+    XCTAssertNotNil(payload.rendezvousInformation);
+    XCTAssertEqual([payload.rendezvousInformation unsignedLongValue], MTRDiscoveryCapabilitiesSoftAP);
 }
 
 - (void)testOnboardingPayloadParser_NFC_WrongType
@@ -178,7 +180,7 @@
     XCTAssertEqual(payload.productID.unsignedIntegerValue, 1);
     XCTAssertEqual(payload.commissioningFlow, MTRCommissioningFlowCustom);
     XCTAssertEqual(payload.version.unsignedIntegerValue, 0);
-    XCTAssertEqual(payload.rendezvousInformation, MTRRendezvousInformationNone);
+    XCTAssertNil(payload.rendezvousInformation);
 }
 
 - (void)testManualParser_Error
@@ -219,7 +221,8 @@
     XCTAssertEqual(payload.productID.unsignedIntegerValue, 1);
     XCTAssertEqual(payload.commissioningFlow, MTRCommissioningFlowStandard);
     XCTAssertEqual(payload.version.unsignedIntegerValue, 5);
-    XCTAssertEqual(payload.rendezvousInformation, MTRRendezvousInformationSoftAP);
+    XCTAssertNotNil(payload.rendezvousInformation);
+    XCTAssertEqual([payload.rendezvousInformation unsignedLongValue], MTRDiscoveryCapabilitiesSoftAP);
 }
 
 - (void)testQRCodeParserWithOptionalData
@@ -239,7 +242,8 @@
     XCTAssertEqual(payload.vendorID.unsignedIntegerValue, 12);
     XCTAssertEqual(payload.productID.unsignedIntegerValue, 1);
     XCTAssertEqual(payload.commissioningFlow, MTRCommissioningFlowStandard);
-    XCTAssertEqual(payload.rendezvousInformation, MTRRendezvousInformationSoftAP);
+    XCTAssertNotNil(payload.rendezvousInformation);
+    XCTAssertEqual([payload.rendezvousInformation unsignedLongValue], MTRDiscoveryCapabilitiesSoftAP);
     XCTAssertTrue([payload.serialNumber isEqualToString:@"123456789"]);
 
     NSArray<MTROptionalQRCodeInfo *> * vendorOptionalInfo = [payload getAllOptionalVendorData:&error];
diff --git a/src/setup_payload/ManualSetupPayloadParser.cpp b/src/setup_payload/ManualSetupPayloadParser.cpp
index ec0a564..3b20e24 100644
--- a/src/setup_payload/ManualSetupPayloadParser.cpp
+++ b/src/setup_payload/ManualSetupPayloadParser.cpp
@@ -27,7 +27,6 @@
 #include <lib/support/logging/CHIPLogging.h>
 #include <lib/support/verhoeff/Verhoeff.h>
 
-#include <math.h>
 #include <string>
 #include <vector>
 
diff --git a/src/setup_payload/QRCodeSetupPayloadGenerator.cpp b/src/setup_payload/QRCodeSetupPayloadGenerator.cpp
index cc55888..c653148 100644
--- a/src/setup_payload/QRCodeSetupPayloadGenerator.cpp
+++ b/src/setup_payload/QRCodeSetupPayloadGenerator.cpp
@@ -168,8 +168,9 @@
         populateBits(bits.data(), offset, payload.productID, kProductIDFieldLengthInBits, kTotalPayloadDataSizeInBits));
     ReturnErrorOnFailure(populateBits(bits.data(), offset, static_cast<uint64_t>(payload.commissioningFlow),
                                       kCommissioningFlowFieldLengthInBits, kTotalPayloadDataSizeInBits));
-    ReturnErrorOnFailure(populateBits(bits.data(), offset, payload.rendezvousInformation.Raw(), kRendezvousInfoFieldLengthInBits,
-                                      kTotalPayloadDataSizeInBits));
+    VerifyOrReturnError(payload.rendezvousInformation.HasValue(), CHIP_ERROR_INVALID_ARGUMENT);
+    ReturnErrorOnFailure(populateBits(bits.data(), offset, payload.rendezvousInformation.Value().Raw(),
+                                      kRendezvousInfoFieldLengthInBits, kTotalPayloadDataSizeInBits));
     ReturnErrorOnFailure(populateBits(bits.data(), offset, payload.discriminator.GetLongValue(),
                                       kPayloadDiscriminatorFieldLengthInBits, kTotalPayloadDataSizeInBits));
     ReturnErrorOnFailure(
diff --git a/src/setup_payload/QRCodeSetupPayloadParser.cpp b/src/setup_payload/QRCodeSetupPayloadParser.cpp
index 340dcf6..98a658b 100644
--- a/src/setup_payload/QRCodeSetupPayloadParser.cpp
+++ b/src/setup_payload/QRCodeSetupPayloadParser.cpp
@@ -24,7 +24,6 @@
 #include "QRCodeSetupPayloadParser.h"
 #include "Base38Decode.h"
 
-#include <math.h>
 #include <memory>
 #include <string.h>
 #include <vector>
@@ -354,7 +353,8 @@
     ReturnErrorOnFailure(readBits(buf, indexToReadFrom, dest, kRendezvousInfoFieldLengthInBits));
     static_assert(kRendezvousInfoFieldLengthInBits <= 8 * sizeof(RendezvousInformationFlag),
                   "Won't fit in RendezvousInformationFlags");
-    outPayload.rendezvousInformation = RendezvousInformationFlags(static_cast<RendezvousInformationFlag>(dest));
+    outPayload.rendezvousInformation.SetValue(
+        RendezvousInformationFlags().SetRaw(static_cast<std::underlying_type_t<RendezvousInformationFlag>>(dest)));
 
     ReturnErrorOnFailure(readBits(buf, indexToReadFrom, dest, kPayloadDiscriminatorFieldLengthInBits));
     static_assert(kPayloadDiscriminatorFieldLengthInBits <= 16, "Won't fit in uint16_t");
diff --git a/src/setup_payload/SetupPayload.cpp b/src/setup_payload/SetupPayload.cpp
index 7b951cd..70b5967 100644
--- a/src/setup_payload/SetupPayload.cpp
+++ b/src/setup_payload/SetupPayload.cpp
@@ -74,7 +74,7 @@
 
     chip::RendezvousInformationFlags allvalid(RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kOnNetwork,
                                               RendezvousInformationFlag::kSoftAP);
-    if (!rendezvousInformation.HasOnly(allvalid))
+    if (!rendezvousInformation.HasValue() || !rendezvousInformation.Value().HasOnly(allvalid))
     {
         return false;
     }
diff --git a/src/setup_payload/SetupPayload.h b/src/setup_payload/SetupPayload.h
index 10c664e..5e503ae 100644
--- a/src/setup_payload/SetupPayload.h
+++ b/src/setup_payload/SetupPayload.h
@@ -29,6 +29,7 @@
 #include <vector>
 
 #include <lib/core/CHIPError.h>
+#include <lib/core/Optional.h>
 #include <lib/support/BitFlags.h>
 #include <lib/support/SetupDiscriminator.h>
 
@@ -115,11 +116,11 @@
  */
 struct PayloadContents
 {
-    uint8_t version                                  = 0;
-    uint16_t vendorID                                = 0;
-    uint16_t productID                               = 0;
-    CommissioningFlow commissioningFlow              = CommissioningFlow::kStandard;
-    RendezvousInformationFlags rendezvousInformation = RendezvousInformationFlag::kNone;
+    uint8_t version                     = 0;
+    uint16_t vendorID                   = 0;
+    uint16_t productID                  = 0;
+    CommissioningFlow commissioningFlow = CommissioningFlow::kStandard;
+    Optional<RendezvousInformationFlags> rendezvousInformation;
     SetupDiscriminator discriminator;
     uint32_t setUpPINCode = 0;
 
diff --git a/src/setup_payload/SetupPayloadHelper.cpp b/src/setup_payload/SetupPayloadHelper.cpp
index ec1ebb0..36fed5a 100644
--- a/src/setup_payload/SetupPayloadHelper.cpp
+++ b/src/setup_payload/SetupPayloadHelper.cpp
@@ -124,8 +124,8 @@
         break;
     case SetupPayloadKey_RendezVousInformation:
         ChipLogDetail(SetupPayload, "Loaded rendezvousInfo: %u", (uint16_t) parameter.uintValue);
-        setupPayload.rendezvousInformation =
-            RendezvousInformationFlags(static_cast<RendezvousInformationFlag>(parameter.uintValue));
+        setupPayload.rendezvousInformation.SetValue(RendezvousInformationFlags().SetRaw(
+            static_cast<std::underlying_type_t<RendezvousInformationFlag>>(parameter.uintValue)));
         break;
     case SetupPayloadKey_Discriminator:
         ChipLogDetail(SetupPayload, "Loaded discriminator: %u", (uint16_t) parameter.uintValue);
diff --git a/src/setup_payload/java/SetupPayloadParser-JNI.cpp b/src/setup_payload/java/SetupPayloadParser-JNI.cpp
index 5243587..20bd80f 100644
--- a/src/setup_payload/java/SetupPayloadParser-JNI.cpp
+++ b/src/setup_payload/java/SetupPayloadParser-JNI.cpp
@@ -122,7 +122,8 @@
     env->SetIntField(setupPayload, discriminator, discriminatorValue);
     env->SetLongField(setupPayload, setUpPinCode, payload.setUpPINCode);
 
-    env->SetObjectField(setupPayload, discoveryCapabilities, CreateCapabilitiesHashSet(env, payload.rendezvousInformation));
+    env->SetObjectField(setupPayload, discoveryCapabilities,
+                        CreateCapabilitiesHashSet(env, payload.rendezvousInformation.ValueOr(RendezvousInformationFlag::kNone)));
 
     jmethodID addOptionalInfoMid =
         env->GetMethodID(setupPayloadClass, "addOptionalQRCodeInfo", "(Lchip/setuppayload/OptionalQRCodeInfo;)V");
@@ -274,7 +275,8 @@
     payload.setUpPINCode = env->GetLongField(jPayload, setUpPinCode);
 
     jobject discoveryCapabilitiesObj = env->GetObjectField(jPayload, discoveryCapabilities);
-    CreateCapabilitiesFromHashSet(env, discoveryCapabilitiesObj, payload.rendezvousInformation);
+    CreateCapabilitiesFromHashSet(env, discoveryCapabilitiesObj,
+                                  payload.rendezvousInformation.Emplace(RendezvousInformationFlag::kNone));
 }
 
 void CreateCapabilitiesFromHashSet(JNIEnv * env, jobject discoveryCapabilitiesObj, RendezvousInformationFlags & flags)
diff --git a/src/setup_payload/tests/TestHelpers.h b/src/setup_payload/tests/TestHelpers.h
index 5786647..8d84791 100644
--- a/src/setup_payload/tests/TestHelpers.h
+++ b/src/setup_payload/tests/TestHelpers.h
@@ -45,11 +45,11 @@
 {
     SetupPayload payload;
 
-    payload.version               = 0;
-    payload.vendorID              = 12;
-    payload.productID             = 1;
-    payload.commissioningFlow     = CommissioningFlow::kStandard;
-    payload.rendezvousInformation = RendezvousInformationFlags(RendezvousInformationFlag::kSoftAP);
+    payload.version           = 0;
+    payload.vendorID          = 12;
+    payload.productID         = 1;
+    payload.commissioningFlow = CommissioningFlow::kStandard;
+    payload.rendezvousInformation.SetValue(RendezvousInformationFlag::kSoftAP);
     payload.discriminator.SetLongValue(128);
     payload.setUpPINCode = 2048;
 
diff --git a/src/setup_payload/tests/TestQRCode.cpp b/src/setup_payload/tests/TestQRCode.cpp
index 2eec6ef..7bedf28 100644
--- a/src/setup_payload/tests/TestQRCode.cpp
+++ b/src/setup_payload/tests/TestQRCode.cpp
@@ -40,28 +40,29 @@
 {
     SetupPayload inPayload = GetDefaultPayload();
 
-    inPayload.rendezvousInformation = RendezvousInformationFlags(RendezvousInformationFlag::kNone);
+    // Not having a value in rendezvousInformation is not allowed for a QR code.
+    inPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kNone);
     NL_TEST_ASSERT(inSuite, CheckWriteRead(inPayload));
 
-    inPayload.rendezvousInformation = RendezvousInformationFlags(RendezvousInformationFlag::kSoftAP);
+    inPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kSoftAP);
     NL_TEST_ASSERT(inSuite, CheckWriteRead(inPayload));
 
-    inPayload.rendezvousInformation = RendezvousInformationFlags(RendezvousInformationFlag::kBLE);
+    inPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kBLE);
     NL_TEST_ASSERT(inSuite, CheckWriteRead(inPayload));
 
-    inPayload.rendezvousInformation = RendezvousInformationFlags(RendezvousInformationFlag::kOnNetwork);
+    inPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kOnNetwork);
     NL_TEST_ASSERT(inSuite, CheckWriteRead(inPayload));
 
-    inPayload.rendezvousInformation =
-        RendezvousInformationFlags(RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork);
+    inPayload.rendezvousInformation.SetValue(
+        RendezvousInformationFlags(RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork));
     NL_TEST_ASSERT(inSuite, CheckWriteRead(inPayload));
 
-    inPayload.rendezvousInformation =
-        RendezvousInformationFlags(RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kOnNetwork);
+    inPayload.rendezvousInformation.SetValue(
+        RendezvousInformationFlags(RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kOnNetwork));
     NL_TEST_ASSERT(inSuite, CheckWriteRead(inPayload));
 
-    inPayload.rendezvousInformation = RendezvousInformationFlags(
-        RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork);
+    inPayload.rendezvousInformation.SetValue(RendezvousInformationFlags(
+        RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork));
     NL_TEST_ASSERT(inSuite, CheckWriteRead(inPayload));
 }
 
@@ -83,12 +84,12 @@
 {
     SetupPayload inPayload = GetDefaultPayload();
 
-    inPayload.version               = static_cast<uint8_t>((1 << kVersionFieldLengthInBits) - 1);
-    inPayload.vendorID              = 0xFFFF;
-    inPayload.productID             = 0xFFFF;
-    inPayload.commissioningFlow     = CommissioningFlow::kCustom;
-    inPayload.rendezvousInformation = RendezvousInformationFlags(
-        RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork);
+    inPayload.version           = static_cast<uint8_t>((1 << kVersionFieldLengthInBits) - 1);
+    inPayload.vendorID          = 0xFFFF;
+    inPayload.productID         = 0xFFFF;
+    inPayload.commissioningFlow = CommissioningFlow::kCustom;
+    inPayload.rendezvousInformation.SetValue(RendezvousInformationFlags(
+        RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork));
     inPayload.discriminator.SetLongValue(static_cast<uint16_t>((1 << kPayloadDiscriminatorFieldLengthInBits) - 1));
     inPayload.setUpPINCode = static_cast<uint32_t>((1 << kSetupPINCodeFieldLengthInBits) - 1);
 
@@ -306,7 +307,7 @@
     RendezvousInformationFlags invalid = RendezvousInformationFlags(
         RendezvousInformationFlag::kBLE, RendezvousInformationFlag::kSoftAP, RendezvousInformationFlag::kOnNetwork);
     invalid.SetRaw(static_cast<uint8_t>(invalid.Raw() + 1));
-    test_payload.rendezvousInformation = invalid;
+    test_payload.rendezvousInformation.SetValue(invalid);
     NL_TEST_ASSERT(inSuite, test_payload.isValidQRCodePayload() == false);
 
     // test invalid setup PIN