Skip to content

Commit 5f1a60b

Browse files
[nrfconnect] Added the Device Appearance attribute to factory data (#26473)
The appearance attribute of the Basic Information cluster has been added to the Factory Data set. That field allows for defining the visible finish of the product's external case finish method, and color hue. - The attribute has been added to the factory data provider and the Factory Data Parser. - The appearance field has been described in the factory data guide.
1 parent 58699c8 commit 5f1a60b

10 files changed

+189
-49
lines changed

config/nrfconnect/chip-module/generate_factory_data.cmake

+5
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ string(APPEND script_args "--discriminator ${CONFIG_CHIP_DEVICE_DISCRIMINATOR}\n
9090
string(APPEND script_args "--passcode ${CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE}\n")
9191
string(APPEND script_args "--include_passcode\n")
9292
string(APPEND script_args "--overwrite\n")
93+
string(APPEND script_args "--product_finish ${CONFIG_CHIP_DEVICE_PRODUCT_FINISH}\n")
94+
95+
if(CONFIG_CHIP_DEVICE_PRODUCT_COLOR)
96+
string(APPEND script_args "--product_color ${CONFIG_CHIP_DEVICE_PRODUCT_COLOR}\n")
97+
endif()
9398

9499
if(CONFIG_CHIP_FACTORY_DATA_GENERATE_ONBOARDING_CODES)
95100
string(APPEND script_args "--generate_onboarding\n")

config/zephyr/Kconfig

+17
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,23 @@ config CHIP_DEVICE_ENABLE_KEY
201201
test action. This value is used during certification tests, and should not
202202
be present on devices in production environment.
203203

204+
config CHIP_DEVICE_PRODUCT_FINISH
205+
string "Description of the product's external case finish method"
206+
default "other"
207+
help
208+
provides a description of the product's external case finish method.
209+
Possible values:
210+
other; matte; satin; polished; rugged; fabric
211+
212+
config CHIP_DEVICE_PRODUCT_COLOR
213+
string "Description of the product's primary color"
214+
help
215+
provides a description of the product's primary color.
216+
Possible values:
217+
black; navy; green; teal; maroon; purple; olive; gray; blue; lime;
218+
aqua; red; fuchsia; yellow; white; nickel; chrome; brass; cooper;
219+
silver; gold.
220+
204221
# Matter optional features and parameters
205222

206223
config CHIP_ENABLE_PAIRING_AUTOSTART

docs/guides/nrfconnect_factory_data_configuration.md

+90-47
Large diffs are not rendered by default.

scripts/tools/nrfconnect/generate_nrfconnect_chip_factory_data.py

+12
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@
6161
PUB_KEY_PREFIX = b'\x04'
6262
INVALID_PASSCODES = [00000000, 11111111, 22222222, 33333333, 44444444,
6363
55555555, 66666666, 77777777, 88888888, 99999999, 12345678, 87654321]
64+
PRODUCT_FINISH_ENUM = {"other": 0, "matte": 1, "satin": 2, "polished": 3, "rugged": 4, "fabric": 5}
65+
PRODUCT_COLOR_ENUM = {"black": 0, "navy": 1, "green": 2, "teal": 3, "maroon": 4, "purple": 5, "olive": 6, "gray": 7, "blue": 8, "lime": 9,
66+
"aqua": 10, "red": 11, "fuchsia": 12, "yellow": 13, "white": 14, "nickel": 15, "chrome": 16, "brass": 18, "cooper": 19,
67+
"silver": 19, "gold": 20}
6468

6569
sys.path.insert(0, os.path.join(MATTER_ROOT, 'scripts', 'tools', 'spake2p'))
6670
from spake2p import generate_verifier # noqa: E402 isort:skip
@@ -325,6 +329,10 @@ def generate_json(self):
325329
self._add_entry("rd_uid", rd_uid)
326330
if self._args.enable_key:
327331
self._add_entry("enable_key", HEX_PREFIX + self._args.enable_key)
332+
if self._args.product_finish:
333+
self._add_entry("product_finish", PRODUCT_FINISH_ENUM[self._args.product_finish])
334+
if self._args.product_color:
335+
self._add_entry("primary_color", PRODUCT_COLOR_ENUM[self._args.product_color])
328336
if self._args.user:
329337
self._add_entry("user", self._user_data)
330338

@@ -516,6 +524,10 @@ def base64_str(s): return base64.b64decode(s)
516524
optional_arguments.add_argument("--generate_onboarding", action="store_true",
517525
help=("Generate a Manual Code and QR Code according to provided factory data set."
518526
"As a result a PNG image containing QRCode and a .txt file containing Manual Code will be available within output directory"))
527+
optional_arguments.add_argument("--product_finish", type=str, choices=PRODUCT_FINISH_ENUM.keys(),
528+
help="[string] Provide one of the product finishes")
529+
optional_arguments.add_argument("--product_color", type=str, choices=PRODUCT_COLOR_ENUM.keys(),
530+
help="[string] Provide one of the product colors.")
519531
args = parser.parse_args()
520532

521533
if args.verbose:

scripts/tools/nrfconnect/nrfconnect_factory_data.schema

+10
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,16 @@
156156
"minLength": 36,
157157
"maxLength": 36
158158
},
159+
"product_finish": {
160+
"description": "Product finish provides a description of the product's external case finish method (matte, satin, polished, rugged, fabric)",
161+
"type": "integer",
162+
"enum": [0, 1, 2, 3, 4, 5]
163+
},
164+
"primary_color": {
165+
"description": "Product finish provides a description of the product's primary color",
166+
"type": "integer",
167+
"enum": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
168+
},
159169
"user": {
160170
"description": "A user-specific additional data which should be added to factory data. This should be a Json format.",
161171
"type": "object"

scripts/tools/nrfconnect/tests/test_generate_factory_data.py

+4
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ def test_generate_factory_data_all_specified(self):
177177
'--discriminator', '0xFED',
178178
'--rd_uid', '91a9c12a7c80700a31ddcfa7fce63e44',
179179
'--enable_key', '00112233445566778899aabbccddeeff',
180+
'--product_color', 'red',
181+
'--product_finish', 'satin',
180182
'--user', '{"name": "product_name", "version": 123, "revision": "0x123"}',
181183
'-o', os.path.join(outdir, 'fd.json')
182184
])
@@ -207,6 +209,8 @@ def test_generate_factory_data_all_specified(self):
207209
self.assertEqual(factory_data.get('passcode'), 13243546)
208210
self.assertEqual(factory_data.get('rd_uid'), 'hex:91a9c12a7c80700a31ddcfa7fce63e44')
209211
self.assertEqual(factory_data.get('enable_key'), 'hex:00112233445566778899aabbccddeeff')
212+
self.assertEqual(factory_data.get('product_finish'), 2)
213+
self.assertEqual(factory_data.get('primary_color'), 11)
210214
self.assertEqual(factory_data.get('user'), {'name': 'product_name', 'version': 123, 'revision': '0x123'})
211215

212216
subprocess.check_call(['python3', os.path.join(TOOLS_DIR, 'nrfconnect_generate_partition.py'),

src/platform/nrfconnect/FactoryDataParser.c

+24-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <ctype.h>
2323
#include <string.h>
2424

25-
#define MAX_FACTORY_DATA_NESTING_LEVEL 3
25+
#define MAX_FACTORY_DATA_NESTING_LEVEL 4
2626

2727
static inline bool uint16_decode(zcbor_state_t * states, uint16_t * value)
2828
{
@@ -37,6 +37,19 @@ static inline bool uint16_decode(zcbor_state_t * states, uint16_t * value)
3737
return false;
3838
}
3939

40+
static inline bool uint8_decode(zcbor_state_t * states, uint8_t * value)
41+
{
42+
uint32_t u32;
43+
44+
if (zcbor_uint32_decode(states, &u32))
45+
{
46+
*value = (uint8_t) u32;
47+
return true;
48+
}
49+
50+
return false;
51+
}
52+
4053
static bool DecodeEntry(zcbor_state_t * states, void * buffer, size_t bufferSize, size_t * outlen)
4154
{
4255
struct zcbor_string tempString;
@@ -233,6 +246,16 @@ bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData
233246
{
234247
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->enable_key);
235248
}
249+
else if (strncmp("product_finish", (const char *) currentString.value, currentString.len) == 0)
250+
{
251+
res = res && uint8_decode(states, &factoryData->product_finish);
252+
factoryData->productFinishPresent = res;
253+
}
254+
else if (strncmp("primary_color", (const char *) currentString.value, currentString.len) == 0)
255+
{
256+
res = res && uint8_decode(states, &factoryData->primary_color);
257+
factoryData->primaryColorPresent = res;
258+
}
236259
else if (strncmp("user", (const char *) currentString.value, currentString.len) == 0)
237260
{
238261
factoryData->user.data = (void *) states->payload;

src/platform/nrfconnect/FactoryDataParser.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,14 @@ struct FactoryData
5858
uint32_t passcode;
5959
struct FactoryDataString enable_key;
6060
struct FactoryDataString user;
61-
61+
uint8_t product_finish;
62+
uint8_t primary_color;
6263
bool vendorIdPresent;
6364
bool productIdPresent;
6465
bool hwVerPresent;
6566
bool discriminatorPresent;
67+
bool productFinishPresent;
68+
bool primaryColorPresent;
6669
};
6770

6871
/**

src/platform/nrfconnect/FactoryDataProvider.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,27 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetEnableKey(MutableByteSpan &
339339
return CHIP_NO_ERROR;
340340
}
341341

342+
template <class FlashFactoryData>
343+
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish)
344+
{
345+
ReturnErrorCodeIf(!finish, CHIP_ERROR_INVALID_ARGUMENT);
346+
ReturnErrorCodeIf(!mFactoryData.productFinishPresent, CHIP_ERROR_NOT_IMPLEMENTED);
347+
*finish = static_cast<app::Clusters::BasicInformation::ProductFinishEnum>(mFactoryData.product_finish);
348+
349+
return CHIP_NO_ERROR;
350+
}
351+
352+
template <class FlashFactoryData>
353+
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor)
354+
{
355+
ReturnErrorCodeIf(!primaryColor, CHIP_ERROR_INVALID_ARGUMENT);
356+
ReturnErrorCodeIf(!mFactoryData.primaryColorPresent, CHIP_ERROR_NOT_IMPLEMENTED);
357+
358+
*primaryColor = static_cast<app::Clusters::BasicInformation::ColorEnum>(mFactoryData.primary_color);
359+
360+
return CHIP_NO_ERROR;
361+
}
362+
342363
template <class FlashFactoryData>
343364
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetUserData(MutableByteSpan & userData)
344365
{

src/platform/nrfconnect/FactoryDataProvider.h

+2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentia
107107
CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
108108
CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override;
109109
CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
110+
CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) override;
111+
CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) override;
110112

111113
// ===== Members functions that are platform-specific
112114
CHIP_ERROR GetEnableKey(MutableByteSpan & enableKey);

0 commit comments

Comments
 (0)