Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nrfconnect] Added the Device Appearance attribute to factory data #26473

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions config/nrfconnect/chip-module/generate_factory_data.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ string(APPEND script_args "--discriminator ${CONFIG_CHIP_DEVICE_DISCRIMINATOR}\n
string(APPEND script_args "--passcode ${CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE}\n")
string(APPEND script_args "--include_passcode\n")
string(APPEND script_args "--overwrite\n")
string(APPEND script_args "--product_finish ${CONFIG_CHIP_DEVICE_PRODUCT_FINISH}\n")

if(CONFIG_CHIP_DEVICE_PRODUCT_COLOR)
string(APPEND script_args "--product_color ${CONFIG_CHIP_DEVICE_PRODUCT_COLOR}\n")
endif()

if(CONFIG_CHIP_FACTORY_DATA_GENERATE_ONBOARDING_CODES)
string(APPEND script_args "--generate_onboarding\n")
Expand Down
17 changes: 17 additions & 0 deletions config/zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,23 @@ config CHIP_DEVICE_ENABLE_KEY
test action. This value is used during certification tests, and should not
be present on devices in production environment.

config CHIP_DEVICE_PRODUCT_FINISH
string "Description of the product's external case finish method"
default "other"
help
provides a description of the product's external case finish method.
Possible values:
other; matte; satin; polished; rugged; fabric

config CHIP_DEVICE_PRODUCT_COLOR
string "Description of the product's primary color"
help
provides a description of the product's primary color.
Possible values:
black; navy; green; teal; maroon; purple; olive; gray; blue; lime;
aqua; red; fuchsia; yellow; white; nickel; chrome; brass; cooper;
silver; gold.

# Matter optional features and parameters

config CHIP_ENABLE_PAIRING_AUTOSTART
Expand Down
137 changes: 90 additions & 47 deletions docs/guides/nrfconnect_factory_data_configuration.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
PUB_KEY_PREFIX = b'\x04'
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}

sys.path.insert(0, os.path.join(MATTER_ROOT, 'scripts', 'tools', 'spake2p'))
from spake2p import generate_verifier # noqa: E402 isort:skip
Expand Down Expand Up @@ -325,6 +329,10 @@ def generate_json(self):
self._add_entry("rd_uid", rd_uid)
if self._args.enable_key:
self._add_entry("enable_key", HEX_PREFIX + self._args.enable_key)
if self._args.product_finish:
self._add_entry("product_finish", PRODUCT_FINISH_ENUM[self._args.product_finish])
if self._args.product_color:
self._add_entry("primary_color", PRODUCT_COLOR_ENUM[self._args.product_color])
if self._args.user:
self._add_entry("user", self._user_data)

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

if args.verbose:
Expand Down
10 changes: 10 additions & 0 deletions scripts/tools/nrfconnect/nrfconnect_factory_data.schema
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@
"minLength": 36,
"maxLength": 36
},
"product_finish": {
"description": "Product finish provides a description of the product's external case finish method (matte, satin, polished, rugged, fabric)",
"type": "integer",
"enum": [0, 1, 2, 3, 4, 5]
},
"primary_color": {
"description": "Product finish provides a description of the product's primary color",
"type": "integer",
"enum": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
},
"user": {
"description": "A user-specific additional data which should be added to factory data. This should be a Json format.",
"type": "object"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ def test_generate_factory_data_all_specified(self):
'--discriminator', '0xFED',
'--rd_uid', '91a9c12a7c80700a31ddcfa7fce63e44',
'--enable_key', '00112233445566778899aabbccddeeff',
'--product_color', 'red',
'--product_finish', 'satin',
'--user', '{"name": "product_name", "version": 123, "revision": "0x123"}',
'-o', os.path.join(outdir, 'fd.json')
])
Expand Down Expand Up @@ -207,6 +209,8 @@ def test_generate_factory_data_all_specified(self):
self.assertEqual(factory_data.get('passcode'), 13243546)
self.assertEqual(factory_data.get('rd_uid'), 'hex:91a9c12a7c80700a31ddcfa7fce63e44')
self.assertEqual(factory_data.get('enable_key'), 'hex:00112233445566778899aabbccddeeff')
self.assertEqual(factory_data.get('product_finish'), 2)
self.assertEqual(factory_data.get('primary_color'), 11)
self.assertEqual(factory_data.get('user'), {'name': 'product_name', 'version': 123, 'revision': '0x123'})

subprocess.check_call(['python3', os.path.join(TOOLS_DIR, 'nrfconnect_generate_partition.py'),
Expand Down
25 changes: 24 additions & 1 deletion src/platform/nrfconnect/FactoryDataParser.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <ctype.h>
#include <string.h>

#define MAX_FACTORY_DATA_NESTING_LEVEL 3
#define MAX_FACTORY_DATA_NESTING_LEVEL 4

static inline bool uint16_decode(zcbor_state_t * states, uint16_t * value)
{
Expand All @@ -37,6 +37,19 @@ static inline bool uint16_decode(zcbor_state_t * states, uint16_t * value)
return false;
}

static inline bool uint8_decode(zcbor_state_t * states, uint8_t * value)
{
uint32_t u32;

if (zcbor_uint32_decode(states, &u32))
{
*value = (uint8_t) u32;
return true;
}

return false;
}

static bool DecodeEntry(zcbor_state_t * states, void * buffer, size_t bufferSize, size_t * outlen)
{
struct zcbor_string tempString;
Expand Down Expand Up @@ -233,6 +246,16 @@ bool ParseFactoryData(uint8_t * buffer, uint16_t bufferSize, struct FactoryData
{
res = res && zcbor_bstr_decode(states, (struct zcbor_string *) &factoryData->enable_key);
}
else if (strncmp("product_finish", (const char *) currentString.value, currentString.len) == 0)
{
res = res && uint8_decode(states, &factoryData->product_finish);
factoryData->productFinishPresent = res;
}
else if (strncmp("primary_color", (const char *) currentString.value, currentString.len) == 0)
{
res = res && uint8_decode(states, &factoryData->primary_color);
factoryData->primaryColorPresent = res;
}
else if (strncmp("user", (const char *) currentString.value, currentString.len) == 0)
{
factoryData->user.data = (void *) states->payload;
Expand Down
5 changes: 4 additions & 1 deletion src/platform/nrfconnect/FactoryDataParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,14 @@ struct FactoryData
uint32_t passcode;
struct FactoryDataString enable_key;
struct FactoryDataString user;

uint8_t product_finish;
uint8_t primary_color;
bool vendorIdPresent;
bool productIdPresent;
bool hwVerPresent;
bool discriminatorPresent;
bool productFinishPresent;
bool primaryColorPresent;
};

/**
Expand Down
21 changes: 21 additions & 0 deletions src/platform/nrfconnect/FactoryDataProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,27 @@ CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetEnableKey(MutableByteSpan &
return CHIP_NO_ERROR;
}

template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish)
{
ReturnErrorCodeIf(!finish, CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorCodeIf(!mFactoryData.productFinishPresent, CHIP_ERROR_NOT_IMPLEMENTED);
*finish = static_cast<app::Clusters::BasicInformation::ProductFinishEnum>(mFactoryData.product_finish);

return CHIP_NO_ERROR;
}

template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor)
{
ReturnErrorCodeIf(!primaryColor, CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorCodeIf(!mFactoryData.primaryColorPresent, CHIP_ERROR_NOT_IMPLEMENTED);

*primaryColor = static_cast<app::Clusters::BasicInformation::ColorEnum>(mFactoryData.primary_color);

return CHIP_NO_ERROR;
}

template <class FlashFactoryData>
CHIP_ERROR FactoryDataProvider<FlashFactoryData>::GetUserData(MutableByteSpan & userData)
{
Expand Down
2 changes: 2 additions & 0 deletions src/platform/nrfconnect/FactoryDataProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentia
CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override;
CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) override;
CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) override;

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