From f9ebabd17e51c201de5eda338b9e4573fe675769 Mon Sep 17 00:00:00 2001
From: shripad621git <shripad62001@gmail.com>
Date: Tue, 16 Jul 2024 23:29:27 +0530
Subject: [PATCH 1/3] Changes to support product-appearance attribute on ESP32.

- Added the support for product-appearance attribute of BasicInformationCluster in factory script.
- Added DeviceInstanceInfoProvider implementation for the attribute.
---
 .../tools/generate_esp32_chip_factory_bin.py  | 26 ++++++++++++++++++-
 src/platform/ESP32/ESP32Config.cpp            |  2 ++
 src/platform/ESP32/ESP32Config.h              |  2 ++
 .../ESP32/ESP32FactoryDataProvider.cpp        | 25 ++++++++++++++++++
 src/platform/ESP32/ESP32FactoryDataProvider.h |  2 ++
 5 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/scripts/tools/generate_esp32_chip_factory_bin.py b/scripts/tools/generate_esp32_chip_factory_bin.py
index eab2ec6b43c229..f3c81dcf5935a8 100755
--- a/scripts/tools/generate_esp32_chip_factory_bin.py
+++ b/scripts/tools/generate_esp32_chip_factory_bin.py
@@ -44,6 +44,10 @@
 
 INVALID_PASSCODES = [00000000, 11111111, 22222222, 33333333, 44444444, 55555555,
                      66666666, 77777777, 88888888, 99999999, 12345678, 87654321]
+PRODUCT_FINISH_ENUM = {"other": 0, "matte": 1, "satin": 2, "polished": 3, "rugged": 4, "fabric": 5}
+PRODUCT_COLOR_ENUM = {"black": 0, "navy": 1, "green": 2, "teal": 3, "maroon": 4, "purple": 5, "olive": 6, "gray": 7, "blue": 8, "lime": 9,
+                      "aqua": 10, "red": 11, "fuchsia": 12, "yellow": 13, "white": 14, "nickel": 15, "chrome": 16, "brass": 18, "cooper": 19,
+                      "silver": 19, "gold": 20}
 
 TOOLS = {}
 
@@ -149,6 +153,16 @@
         'encoding': 'hex2bin',
         'value': None,
     },
+    'product-finish': {
+        'type': 'data',
+        'encoding': 'u32',
+        'value': None,
+    },
+    'product-color': {
+        'type': 'data',
+        'encoding': 'u32',
+        'value': None,
+    },
 }
 
 
@@ -301,6 +315,10 @@ def populate_factory_data(args, spake2p_params):
         FACTORY_DATA['hardware-ver']['value'] = args.hw_ver
     if args.hw_ver_str:
         FACTORY_DATA['hw-ver-str']['value'] = args.hw_ver_str
+    if args.product_finish:
+        FACTORY_DATA['product-finish']['value'] = PRODUCT_FINISH_ENUM[args.product_finish]
+    if args.product_color:
+        FACTORY_DATA['product-color']['value'] = PRODUCT_COLOR_ENUM[args.product_color]
 
     # SupportedModes are stored as multiple entries
     #  - sm-sz/<ep>                 : number of supported modes for the endpoint
@@ -471,6 +489,11 @@ def any_base_int(s): return int(s, 0)
     parser.add_argument('--supported-modes', type=str, nargs='+', required=False,
                         help='List of supported modes, eg: mode1/label1/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode"  mode2/label2/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode"  mode3/label3/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode"')
 
+    parser.add_argument("--product-finish", type=str, choices=PRODUCT_FINISH_ENUM.keys(),
+                        help='Product finishes choices for product appearance')
+    parser.add_argument("--product-color", type=str, choices=PRODUCT_COLOR_ENUM.keys(),
+                        help='Product colors choices for product appearance')
+
     parser.add_argument('-s', '--size', type=any_base_int, default=0x6000,
                         help='The size of the partition.bin, default: 0x6000')
     parser.add_argument('--target', default='esp32',
@@ -509,7 +532,8 @@ def set_up_factory_data(args):
 def generate_factory_partiton_binary(args):
     generate_nvs_csv(args.output_dir, FACTORY_PARTITION_CSV)
     if args.generate_bin:
-        generate_nvs_bin(args.encrypt, args.size, FACTORY_PARTITION_CSV, FACTORY_PARTITION_BIN, args.output_dir)
+        csv_file = os.path.join(args.output_dir, FACTORY_PARTITION_CSV)
+        generate_nvs_bin(args.encrypt, args.size, csv_file, FACTORY_PARTITION_BIN, args.output_dir)
         print_flashing_help(args.encrypt, args.output_dir, FACTORY_PARTITION_BIN)
     clean_up()
 
diff --git a/src/platform/ESP32/ESP32Config.cpp b/src/platform/ESP32/ESP32Config.cpp
index 04e02f63004207..162fff1f323587 100644
--- a/src/platform/ESP32/ESP32Config.cpp
+++ b/src/platform/ESP32/ESP32Config.cpp
@@ -77,6 +77,8 @@ const ESP32Config::Key ESP32Config::kConfigKey_ProductURL            = { kConfig
 const ESP32Config::Key ESP32Config::kConfigKey_SupportedCalTypes     = { kConfigNamespace_ChipFactory, "cal-types" };
 const ESP32Config::Key ESP32Config::kConfigKey_SupportedLocaleSize   = { kConfigNamespace_ChipFactory, "locale-sz" };
 const ESP32Config::Key ESP32Config::kConfigKey_RotatingDevIdUniqueId = { kConfigNamespace_ChipFactory, "rd-id-uid" };
+const ESP32Config::Key ESP32Config::kConfigKey_ProductFinish         = { kConfigNamespace_ChipFactory, "product-finish" };
+const ESP32Config::Key ESP32Config::kConfigKey_ProductColor          = { kConfigNamespace_ChipFactory, "product-color" };
 const ESP32Config::Key ESP32Config::kConfigKey_LocationCapability    = { kConfigNamespace_ChipFactory, "loc-capability" };
 
 // Keys stored in the chip-config namespace
diff --git a/src/platform/ESP32/ESP32Config.h b/src/platform/ESP32/ESP32Config.h
index 5804f53105c20c..546c593387db72 100644
--- a/src/platform/ESP32/ESP32Config.h
+++ b/src/platform/ESP32/ESP32Config.h
@@ -79,6 +79,8 @@ class ESP32Config
     static const Key kConfigKey_SupportedCalTypes;
     static const Key kConfigKey_SupportedLocaleSize;
     static const Key kConfigKey_RotatingDevIdUniqueId;
+    static const Key kConfigKey_ProductFinish;
+    static const Key kConfigKey_ProductColor;
     static const Key kConfigKey_LocationCapability;
 
     // CHIP Config keys
diff --git a/src/platform/ESP32/ESP32FactoryDataProvider.cpp b/src/platform/ESP32/ESP32FactoryDataProvider.cpp
index 95d2be5c5d1957..7ac2841cc18553 100644
--- a/src/platform/ESP32/ESP32FactoryDataProvider.cpp
+++ b/src/platform/ESP32/ESP32FactoryDataProvider.cpp
@@ -245,6 +245,31 @@ CHIP_ERROR ESP32FactoryDataProvider::GetManufacturingDate(uint16_t & year, uint8
     return GenericDeviceInstanceInfoProvider<ESP32Config>::GetManufacturingDate(year, month, day);
 }
 
+CHIP_ERROR ESP32FactoryDataProvider::GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish)
+{
+    CHIP_ERROR err         = CHIP_NO_ERROR;
+    uint32_t productFinish = 0;
+
+    err = ESP32Config::ReadConfigValue(ESP32Config::kConfigKey_ProductFinish, productFinish);
+    ReturnErrorOnFailure(err);
+    *finish = static_cast<app::Clusters::BasicInformation::ProductFinishEnum>(productFinish);
+
+    return err;
+}
+
+CHIP_ERROR ESP32FactoryDataProvider::GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    uint32_t color = 0;
+
+    err = ESP32Config::ReadConfigValue(ESP32Config::kConfigKey_ProductColor, color);
+    ReturnErrorOnFailure(err);
+
+    *primaryColor = static_cast<app::Clusters::BasicInformation::ColorEnum>(color);
+
+    return err;
+}
+
 CHIP_ERROR ESP32FactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersion)
 {
     return GenericDeviceInstanceInfoProvider<ESP32Config>::GetHardwareVersion(hardwareVersion);
diff --git a/src/platform/ESP32/ESP32FactoryDataProvider.h b/src/platform/ESP32/ESP32FactoryDataProvider.h
index 1d78f2c2e8fa0b..148b68077cb7d4 100644
--- a/src/platform/ESP32/ESP32FactoryDataProvider.h
+++ b/src/platform/ESP32/ESP32FactoryDataProvider.h
@@ -96,6 +96,8 @@ class ESP32FactoryDataProvider : public CommissionableDataProvider,
     CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
     CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override;
     CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
+    CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish);
+    CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor);
 #endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
 
 private:

From 7084a0cb7a9c8f85aeaa356bf91cf1fb13902ffb Mon Sep 17 00:00:00 2001
From: shripad621git <shripad62001@gmail.com>
Date: Mon, 22 Jul 2024 11:23:54 +0530
Subject: [PATCH 2/3] Addressed review comments

---
 .../tools/generate_esp32_chip_factory_bin.py  | 50 ++++++++++++++++---
 .../ESP32/ESP32FactoryDataProvider.cpp        |  5 +-
 src/platform/ESP32/ESP32FactoryDataProvider.h |  4 +-
 3 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/scripts/tools/generate_esp32_chip_factory_bin.py b/scripts/tools/generate_esp32_chip_factory_bin.py
index f3c81dcf5935a8..c778b7c141ab7b 100755
--- a/scripts/tools/generate_esp32_chip_factory_bin.py
+++ b/scripts/tools/generate_esp32_chip_factory_bin.py
@@ -21,6 +21,7 @@
 import logging
 import os
 import sys
+from enum import Enum
 from types import SimpleNamespace
 
 import cryptography.x509
@@ -44,10 +45,40 @@
 
 INVALID_PASSCODES = [00000000, 11111111, 22222222, 33333333, 44444444, 55555555,
                      66666666, 77777777, 88888888, 99999999, 12345678, 87654321]
-PRODUCT_FINISH_ENUM = {"other": 0, "matte": 1, "satin": 2, "polished": 3, "rugged": 4, "fabric": 5}
-PRODUCT_COLOR_ENUM = {"black": 0, "navy": 1, "green": 2, "teal": 3, "maroon": 4, "purple": 5, "olive": 6, "gray": 7, "blue": 8, "lime": 9,
-                      "aqua": 10, "red": 11, "fuchsia": 12, "yellow": 13, "white": 14, "nickel": 15, "chrome": 16, "brass": 18, "cooper": 19,
-                      "silver": 19, "gold": 20}
+
+
+class Product_Finish_Enum(Enum):
+    other = 0
+    matte = 1
+    satin = 2
+    polished = 3
+    rugged = 4
+    fabric = 5
+
+
+class Product_Color_Enum(Enum):
+    black = 0
+    navy = 1
+    green = 2
+    teal = 3
+    maroon = 4
+    purple = 5
+    olive = 6
+    gray = 7
+    blue = 8
+    lime = 9
+    aqua = 10
+    red = 11
+    fuchsia = 12
+    yellow = 13
+    white = 14
+    nickel = 15
+    chrome = 16
+    brass = 17
+    copper = 18
+    silver = 19
+    gold = 20
+
 
 TOOLS = {}
 
@@ -316,9 +347,9 @@ def populate_factory_data(args, spake2p_params):
     if args.hw_ver_str:
         FACTORY_DATA['hw-ver-str']['value'] = args.hw_ver_str
     if args.product_finish:
-        FACTORY_DATA['product-finish']['value'] = PRODUCT_FINISH_ENUM[args.product_finish]
+        FACTORY_DATA['product-finish']['value'] = Product_Finish_Enum[args.product_finish].value
     if args.product_color:
-        FACTORY_DATA['product-color']['value'] = PRODUCT_COLOR_ENUM[args.product_color]
+        FACTORY_DATA['product-color']['value'] = Product_Color_Enum[args.product_color].value
 
     # SupportedModes are stored as multiple entries
     #  - sm-sz/<ep>                 : number of supported modes for the endpoint
@@ -489,9 +520,12 @@ def any_base_int(s): return int(s, 0)
     parser.add_argument('--supported-modes', type=str, nargs='+', required=False,
                         help='List of supported modes, eg: mode1/label1/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode"  mode2/label2/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode"  mode3/label3/ep/"tagValue1\\mfgCode, tagValue2\\mfgCode"')
 
-    parser.add_argument("--product-finish", type=str, choices=PRODUCT_FINISH_ENUM.keys(),
+    product_finish_choices = [finish.name for finish in Product_Finish_Enum]
+    parser.add_argument("--product-finish", type=str, choices=product_finish_choices,
                         help='Product finishes choices for product appearance')
-    parser.add_argument("--product-color", type=str, choices=PRODUCT_COLOR_ENUM.keys(),
+
+    product_color_choices = [color.name for color in Product_Color_Enum]
+    parser.add_argument("--product-color", type=str, choices=product_color_choices,
                         help='Product colors choices for product appearance')
 
     parser.add_argument('-s', '--size', type=any_base_int, default=0x6000,
diff --git a/src/platform/ESP32/ESP32FactoryDataProvider.cpp b/src/platform/ESP32/ESP32FactoryDataProvider.cpp
index 7ac2841cc18553..b6120ff4e66857 100644
--- a/src/platform/ESP32/ESP32FactoryDataProvider.cpp
+++ b/src/platform/ESP32/ESP32FactoryDataProvider.cpp
@@ -251,7 +251,8 @@ CHIP_ERROR ESP32FactoryDataProvider::GetProductFinish(app::Clusters::BasicInform
     uint32_t productFinish = 0;
 
     err = ESP32Config::ReadConfigValue(ESP32Config::kConfigKey_ProductFinish, productFinish);
-    ReturnErrorOnFailure(err);
+    ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED);
+
     *finish = static_cast<app::Clusters::BasicInformation::ProductFinishEnum>(productFinish);
 
     return err;
@@ -263,7 +264,7 @@ CHIP_ERROR ESP32FactoryDataProvider::GetProductPrimaryColor(app::Clusters::Basic
     uint32_t color = 0;
 
     err = ESP32Config::ReadConfigValue(ESP32Config::kConfigKey_ProductColor, color);
-    ReturnErrorOnFailure(err);
+    ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED);
 
     *primaryColor = static_cast<app::Clusters::BasicInformation::ColorEnum>(color);
 
diff --git a/src/platform/ESP32/ESP32FactoryDataProvider.h b/src/platform/ESP32/ESP32FactoryDataProvider.h
index 148b68077cb7d4..08227ed4ed143b 100644
--- a/src/platform/ESP32/ESP32FactoryDataProvider.h
+++ b/src/platform/ESP32/ESP32FactoryDataProvider.h
@@ -96,8 +96,8 @@ class ESP32FactoryDataProvider : public CommissionableDataProvider,
     CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
     CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override;
     CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
-    CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish);
-    CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor);
+    CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) override;
+    CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) override;
 #endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER
 
 private:

From adf2bb372db28bee6db630caee28adeebe7cbd92 Mon Sep 17 00:00:00 2001
From: shripad621git <shripad62001@gmail.com>
Date: Tue, 23 Jul 2024 16:32:26 +0530
Subject: [PATCH 3/3] Changes to support few more missing attributes

---
 .../tools/generate_esp32_chip_factory_bin.py  | 25 +++++++++++++++++++
 src/platform/ESP32/ESP32Config.cpp            |  1 +
 src/platform/ESP32/ESP32Config.h              |  1 +
 .../ESP32/ESP32FactoryDataProvider.cpp        |  7 +++++-
 4 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/scripts/tools/generate_esp32_chip_factory_bin.py b/scripts/tools/generate_esp32_chip_factory_bin.py
index c778b7c141ab7b..b19748ca31b197 100755
--- a/scripts/tools/generate_esp32_chip_factory_bin.py
+++ b/scripts/tools/generate_esp32_chip_factory_bin.py
@@ -194,6 +194,21 @@ class Product_Color_Enum(Enum):
         'encoding': 'u32',
         'value': None,
     },
+    'part-number': {
+        'type': 'data',
+        'encoding': 'string',
+        'value': None,
+    },
+    'product-label': {
+        'type': 'data',
+        'encoding': 'string',
+        'value': None,
+    },
+    'product-url': {
+        'type': 'data',
+        'encoding': 'string',
+        'value': None,
+    },
 }
 
 
@@ -350,6 +365,12 @@ def populate_factory_data(args, spake2p_params):
         FACTORY_DATA['product-finish']['value'] = Product_Finish_Enum[args.product_finish].value
     if args.product_color:
         FACTORY_DATA['product-color']['value'] = Product_Color_Enum[args.product_color].value
+    if args.part_number:
+        FACTORY_DATA['part-number']['value'] = args.part_number
+    if args.product_url:
+        FACTORY_DATA['product-url']['value'] = args.product_url
+    if args.product_label:
+        FACTORY_DATA['product-label']['value'] = args.product_label
 
     # SupportedModes are stored as multiple entries
     #  - sm-sz/<ep>                 : number of supported modes for the endpoint
@@ -528,6 +549,10 @@ def any_base_int(s): return int(s, 0)
     parser.add_argument("--product-color", type=str, choices=product_color_choices,
                         help='Product colors choices for product appearance')
 
+    parser.add_argument("--part-number", type=str, help='human readable product number')
+    parser.add_argument("--product-label", type=str, help='human readable product label')
+    parser.add_argument("--product-url", type=str, help='link to product specific web page')
+
     parser.add_argument('-s', '--size', type=any_base_int, default=0x6000,
                         help='The size of the partition.bin, default: 0x6000')
     parser.add_argument('--target', default='esp32',
diff --git a/src/platform/ESP32/ESP32Config.cpp b/src/platform/ESP32/ESP32Config.cpp
index 162fff1f323587..c94de5c04b85b2 100644
--- a/src/platform/ESP32/ESP32Config.cpp
+++ b/src/platform/ESP32/ESP32Config.cpp
@@ -79,6 +79,7 @@ const ESP32Config::Key ESP32Config::kConfigKey_SupportedLocaleSize   = { kConfig
 const ESP32Config::Key ESP32Config::kConfigKey_RotatingDevIdUniqueId = { kConfigNamespace_ChipFactory, "rd-id-uid" };
 const ESP32Config::Key ESP32Config::kConfigKey_ProductFinish         = { kConfigNamespace_ChipFactory, "product-finish" };
 const ESP32Config::Key ESP32Config::kConfigKey_ProductColor          = { kConfigNamespace_ChipFactory, "product-color" };
+const ESP32Config::Key ESP32Config::kConfigKey_PartNumber            = { kConfigNamespace_ChipFactory, "part-number" };
 const ESP32Config::Key ESP32Config::kConfigKey_LocationCapability    = { kConfigNamespace_ChipFactory, "loc-capability" };
 
 // Keys stored in the chip-config namespace
diff --git a/src/platform/ESP32/ESP32Config.h b/src/platform/ESP32/ESP32Config.h
index 546c593387db72..218f2354b2b358 100644
--- a/src/platform/ESP32/ESP32Config.h
+++ b/src/platform/ESP32/ESP32Config.h
@@ -75,6 +75,7 @@ class ESP32Config
     static const Key kConfigKey_ProductId;
     static const Key kConfigKey_ProductName;
     static const Key kConfigKey_ProductLabel;
+    static const Key kConfigKey_PartNumber;
     static const Key kConfigKey_ProductURL;
     static const Key kConfigKey_SupportedCalTypes;
     static const Key kConfigKey_SupportedLocaleSize;
diff --git a/src/platform/ESP32/ESP32FactoryDataProvider.cpp b/src/platform/ESP32/ESP32FactoryDataProvider.cpp
index b6120ff4e66857..ace2a087de144b 100644
--- a/src/platform/ESP32/ESP32FactoryDataProvider.cpp
+++ b/src/platform/ESP32/ESP32FactoryDataProvider.cpp
@@ -278,7 +278,12 @@ CHIP_ERROR ESP32FactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersi
 
 CHIP_ERROR ESP32FactoryDataProvider::GetPartNumber(char * buf, size_t bufSize)
 {
-    return GenericDeviceInstanceInfoProvider<ESP32Config>::GetPartNumber(buf, bufSize);
+    CHIP_ERROR err = ESP32Config::ReadConfigValueStr(ESP32Config::kConfigKey_PartNumber, buf, bufSize, bufSize);
+    if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
+    {
+        return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
+    }
+    return err;
 }
 #endif // CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER