mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
mfg_tool: Generate onboarding payloads using chip-tool
qrcodetool behaves differently on macos and linux which breaks the mfg_tool.py on linux. chip-tool has the facility to generate the onboarding payloads. Unique-id belongs to chip-factory namespace and it was present in chip-config, fixed it.
This commit is contained in:
@@ -7,8 +7,8 @@ chip-cert provides command line interface (CLI) utility used for generating and
|
|||||||
* [SPAKE2P Parameters Tool](https://github.com/project-chip/connectedhomeip/tree/master/src/tools/spake2p),
|
* [SPAKE2P Parameters Tool](https://github.com/project-chip/connectedhomeip/tree/master/src/tools/spake2p),
|
||||||
spake2p tool provides command line interface (CLI) utility used for generating spake parameters (PIN code and verifier) for device manufacturing provisioning.
|
spake2p tool provides command line interface (CLI) utility used for generating spake parameters (PIN code and verifier) for device manufacturing provisioning.
|
||||||
|
|
||||||
* [QR Code Tool](https://github.com/project-chip/connectedhomeip/tree/master/src/qrcodetool),
|
* [chip-tool](https://github.com/project-chip/connectedhomeip/tree/master/examples/chip-tool),
|
||||||
qrcodetool generates onboarding QR code payload and manual pairing code.
|
chip-tool supports generating onboarding QR code payload and manual pairing code.
|
||||||
|
|
||||||
* [Mass Manufacturing Utility](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/mass_mfg.html#manufacturing-utility),
|
* [Mass Manufacturing Utility](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/mass_mfg.html#manufacturing-utility),
|
||||||
mfg_gen.py to create factory NVS partition images.
|
mfg_gen.py to create factory NVS partition images.
|
||||||
@@ -30,16 +30,6 @@ ninja -C out/host
|
|||||||
```
|
```
|
||||||
Above commands will generate spake2p and chip-cert at `esp-matter/connectedhomeip/connectedhomeip/out/host`.
|
Above commands will generate spake2p and chip-cert at `esp-matter/connectedhomeip/connectedhomeip/out/host`.
|
||||||
|
|
||||||
#### Build qrcodetool
|
|
||||||
```
|
|
||||||
cd path/to/esp-matter/connectedhomeip/connectedhomeip
|
|
||||||
ninja -C out/host src/qrcodetool
|
|
||||||
|
|
||||||
# This builds the qrcodetool at path out/host/obj/src/qrcodetool/bin
|
|
||||||
# Move this to out/host to keep all the tools at the same path
|
|
||||||
cp out/host/obj/src/qrcodetool/bin/qrcodetool out/host
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Add the tools path to $PATH
|
#### Add the tools path to $PATH
|
||||||
```
|
```
|
||||||
export PATH="$PATH:path/to/esp-matter/connectedhomeip/connectedhomeip/out/host"
|
export PATH="$PATH:path/to/esp-matter/connectedhomeip/connectedhomeip/out/host"
|
||||||
|
|||||||
@@ -60,11 +60,9 @@ CHIP_KEY_MAP = {
|
|||||||
'type': 'file',
|
'type': 'file',
|
||||||
'encoding': 'binary',
|
'encoding': 'binary',
|
||||||
},
|
},
|
||||||
},
|
|
||||||
'chip-config': {
|
|
||||||
'unique-id': {
|
'unique-id': {
|
||||||
'type': 'data',
|
'type': 'data',
|
||||||
'encoding': 'string',
|
'encoding': 'hex2bin',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+53
-40
@@ -43,7 +43,7 @@ if not os.getenv('IDF_PATH'):
|
|||||||
TOOLS = {
|
TOOLS = {
|
||||||
'spake2p' : None,
|
'spake2p' : None,
|
||||||
'chip-cert' : None,
|
'chip-cert' : None,
|
||||||
'qrcodetool': None,
|
'chip-tool': None,
|
||||||
'mfg_gen' : None,
|
'mfg_gen' : None,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +74,11 @@ INVALID_PASSCODES = [ 00000000, 11111111, 22222222, 33333333, 44444444, 55555555
|
|||||||
|
|
||||||
UUIDs = list()
|
UUIDs = list()
|
||||||
|
|
||||||
|
# Lengths for manual pairing codes and qrcode
|
||||||
|
SHORT_MANUALCODE_LEN = 11
|
||||||
|
LONG_MANUALCODE_LEN = 21
|
||||||
|
QRCODE_LEN = 22
|
||||||
|
|
||||||
def vid_pid_str(vid, pid):
|
def vid_pid_str(vid, pid):
|
||||||
return '_'.join([hex(vid)[2:], hex(pid)[2:]])
|
return '_'.join([hex(vid)[2:], hex(pid)[2:]])
|
||||||
|
|
||||||
@@ -91,9 +96,9 @@ def check_tools_exists():
|
|||||||
logging.error('chip-cert not found, please add chip-cert path to PATH environment variable')
|
logging.error('chip-cert not found, please add chip-cert path to PATH environment variable')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
TOOLS['qrcodetool'] = shutil.which('qrcodetool')
|
TOOLS['chip-tool'] = shutil.which('chip-tool')
|
||||||
if TOOLS['qrcodetool'] is None:
|
if TOOLS['chip-tool'] is None:
|
||||||
logging.error('qrcodetool not found, please add qrcodetool path to PATH environment variable')
|
logging.error('chip-tool not found, please add chip-tool path to PATH environment variable')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
TOOLS['mfg_gen'] = os.sep.join([os.getenv('IDF_PATH'), 'tools', 'mass_mfg', 'mfg_gen.py'])
|
TOOLS['mfg_gen'] = os.sep.join([os.getenv('IDF_PATH'), 'tools', 'mass_mfg', 'mfg_gen.py'])
|
||||||
@@ -104,7 +109,7 @@ def check_tools_exists():
|
|||||||
logging.debug('Using following tools:')
|
logging.debug('Using following tools:')
|
||||||
logging.debug('spake2p: {}'.format(TOOLS['spake2p']))
|
logging.debug('spake2p: {}'.format(TOOLS['spake2p']))
|
||||||
logging.debug('chip-cert: {}'.format(TOOLS['chip-cert']))
|
logging.debug('chip-cert: {}'.format(TOOLS['chip-cert']))
|
||||||
logging.debug('qrcodetool: {}'.format(TOOLS['qrcodetool']))
|
logging.debug('chip-tool: {}'.format(TOOLS['chip-tool']))
|
||||||
logging.debug('mfg_gen: {}'.format(TOOLS['mfg_gen']))
|
logging.debug('mfg_gen: {}'.format(TOOLS['mfg_gen']))
|
||||||
|
|
||||||
def execute_cmd(cmd):
|
def execute_cmd(cmd):
|
||||||
@@ -457,46 +462,55 @@ def generate_partitions(suffix, size):
|
|||||||
]
|
]
|
||||||
execute_cmd(cmd)
|
execute_cmd(cmd)
|
||||||
|
|
||||||
def get_setup_payload_data(args, discriminator, passcode):
|
def get_manualcode_args(args, discriminator, passcode):
|
||||||
data = 'version 0\n'
|
payload_args = list()
|
||||||
data += 'vendorID ' + str(args.vendor_id) + '\n'
|
payload_args.append('--discriminator')
|
||||||
data += 'productID ' + str(args.product_id) + '\n'
|
payload_args.append(str(discriminator))
|
||||||
data += 'commissioningFlow ' + str(args.commissioning_flow) + '\n'
|
payload_args.append('--setup-pin-code')
|
||||||
data += 'rendezVousInformation ' + str(1 << args.discovery_mode) + '\n'
|
payload_args.append(str(passcode))
|
||||||
data += 'discriminator ' + str(discriminator) + '\n'
|
payload_args.append('--version')
|
||||||
data += 'setUpPINCode ' + str(passcode) + '\n'
|
payload_args.append('0')
|
||||||
return data
|
payload_args.append('--vendor-id')
|
||||||
|
payload_args.append(str(args.vendor_id))
|
||||||
|
payload_args.append('--product-id')
|
||||||
|
payload_args.append(str(args.product_id))
|
||||||
|
payload_args.append('--commissioning-mode')
|
||||||
|
payload_args.append(str(args.commissioning_flow))
|
||||||
|
return payload_args
|
||||||
|
|
||||||
def get_chip_qrcode(file):
|
def get_qrcode_args(args, discriminator, passcode):
|
||||||
data = subprocess.check_output([TOOLS['qrcodetool'], 'generate-qr-code', '-f', file])
|
payload_args = get_manualcode_args(args, discriminator, passcode)
|
||||||
data = data.decode('utf-8').splitlines()
|
payload_args.append('--rendezvous')
|
||||||
qrcodeline = data[-1].split(': ')
|
payload_args.append(str(1 << args.discovery_mode))
|
||||||
|
return payload_args
|
||||||
|
|
||||||
if qrcodeline[1] == 'QR Code':
|
def get_chip_qrcode(payload_args):
|
||||||
return qrcodeline[-1]
|
cmd_args = [TOOLS['chip-tool'], 'payload', 'generate-qrcode']
|
||||||
else:
|
cmd_args.extend(payload_args)
|
||||||
logging.error('Failed to generate QR code')
|
data = subprocess.check_output(cmd_args)
|
||||||
return None
|
|
||||||
|
|
||||||
def get_chip_manualcode(file):
|
# Command output is as below:
|
||||||
data = subprocess.check_output([TOOLS['qrcodetool'], 'generate-manual-code', '-f', file])
|
# \x1b[0;32m[1655386003372] [23483:7823617] CHIP: [TOO] QR Code: MT:Y.K90-WB010E7648G00\x1b[0m
|
||||||
data = data.decode('utf-8').splitlines()
|
return data.decode('utf-8').split('QR Code: ')[1][:QRCODE_LEN]
|
||||||
manualcodeline = data[-1].split(': ')
|
|
||||||
|
|
||||||
if manualcodeline[1] == 'Manual Code':
|
def get_chip_manualcode(payload_args, commissioning_flow):
|
||||||
return manualcodeline[-1]
|
cmd_args = [TOOLS['chip-tool'], 'payload', 'generate-manualcode']
|
||||||
else:
|
cmd_args.extend(payload_args)
|
||||||
logging.error('Failed to generate manual code')
|
data = subprocess.check_output(cmd_args)
|
||||||
return None
|
|
||||||
|
# Command output is as below:
|
||||||
|
# \x1b[0;32m[1655386909774] [24424:7837894] CHIP: [TOO] Manual Code: 749721123365521327689\x1b[0m\n
|
||||||
|
# OR
|
||||||
|
# \x1b[0;32m[1655386926028] [24458:7838229] CHIP: [TOO] Manual Code: 34972112338\x1b[0m\n
|
||||||
|
# Length of manual code depends on the commissioning flow:
|
||||||
|
# For standard commissioning flow it is 11 digits
|
||||||
|
# For User-intent and custom commissioning flow it is 21 digits
|
||||||
|
manual_code_len = LONG_MANUALCODE_LEN if commissioning_flow else SHORT_MANUALCODE_LEN
|
||||||
|
return data.decode('utf-8').split('Manual Code: ')[1][:manual_code_len]
|
||||||
|
|
||||||
def generate_onboarding_data(args, index, discriminator, passcode):
|
def generate_onboarding_data(args, index, discriminator, passcode):
|
||||||
setup_payload_file = os.sep.join(['', 'tmp', 'setup_payload_{}.txt'.format(args.vendor_id, args.product_id)])
|
chip_manualcode = get_chip_manualcode(get_manualcode_args(args, discriminator, passcode), args.commissioning_flow)
|
||||||
|
chip_qrcode = get_chip_qrcode(get_qrcode_args(args, discriminator, passcode))
|
||||||
with open(setup_payload_file, 'w') as f:
|
|
||||||
f.write(get_setup_payload_data(args, discriminator, passcode))
|
|
||||||
|
|
||||||
chip_qrcode = get_chip_qrcode(setup_payload_file)
|
|
||||||
chip_manualcode = get_chip_manualcode(setup_payload_file)
|
|
||||||
|
|
||||||
logging.info('Generated QR code: ' + chip_qrcode)
|
logging.info('Generated QR code: ' + chip_qrcode)
|
||||||
logging.info('Generated manual code: ' + chip_manualcode)
|
logging.info('Generated manual code: ' + chip_manualcode)
|
||||||
@@ -514,7 +528,6 @@ def generate_onboarding_data(args, index, discriminator, passcode):
|
|||||||
chip_qr = pyqrcode.create(chip_qrcode, version=2, error='M')
|
chip_qr = pyqrcode.create(chip_qrcode, version=2, error='M')
|
||||||
chip_qr.png(qrcode_file, scale=6)
|
chip_qr.png(qrcode_file, scale=6)
|
||||||
|
|
||||||
os.remove(setup_payload_file)
|
|
||||||
logging.info('Generated onboarding data and QR Code')
|
logging.info('Generated onboarding data and QR Code')
|
||||||
|
|
||||||
def validate_args(args):
|
def validate_args(args):
|
||||||
|
|||||||
Reference in New Issue
Block a user