[mfg_tool] Replaces spake2p, mfg_gen, chip-tool binary executable usages in 'tools/mfg_tool/mfg_tool.py' with respective python implementations - spake2p.py, mfg_gen.py, generate_setup_payload.py

Removes functions get_chip_qrcode, get_chip_manualcode, get_qrcode_args & get_manualcode_args from 'tools/mfg_tool/utlis.py'
Adds python_stdnum dependency for using 'tools/mfg_tool/mfg_tool.py' in `tools/mfg_tool/requirements.txt'

Signed-off-by: dhairyashah1 <dhairya.shah@espressif.com>

[mfg_tool] Adds python_stdnum dependency for using mfg_tool.py in 'requirements.txt'

Signed-off-by: dhairyashah1 <dhairya.shah@espressif.com>

mfg_tool: Adds mfg_tool dependencies reinstallation note in 'RELEASE_NOTES.md'

Signed-off-by: dhairyashah1 <dhairya.shah@espressif.com>

[mfg_tool] Adds details on reinstalling tools/mfg_tool dependencies

Signed-off-by: dhairyashah1 <dhairya.shah@espressif.com>
This commit is contained in:
dhairyashah1
2023-04-06 20:43:31 +05:30
parent fde2c7ea84
commit 08a56856a2
4 changed files with 58 additions and 108 deletions
+9
View File
@@ -1,3 +1,12 @@
# 7-April-2023
- `tools/mfg_tool/mfg_tool.py` now uses `connectedhomeip/connectedhomeip/src/setup_payload/python/generate_setup_payload.py` instead of previously used compiled `chip-tool` binary executable which additionally depends on `python-stdnum` module.
- Reinstall dependencies to use `mfg_tool` by running the following commands -
```
source $IDF_PATH/export.sh
python3 -m pip install -r tools/mfg_tool/requirements.txt
```
# 15-March-2023
API Change
+48 -51
View File
@@ -23,6 +23,7 @@ import sys
import csv
import uuid
import shutil
import base64
import random
import logging
import binascii
@@ -32,16 +33,27 @@ import pyqrcode
from chip_nvs import *
from utils import *
from datetime import datetime
from types import SimpleNamespace
if not os.getenv('IDF_PATH'):
logging.error("IDF_PATH environment variable is not set")
sys.exit(1)
if not os.getenv('ESP_MATTER_PATH'):
logging.error("ESP_MATTER_PATH environment variable is not set")
sys.exit(1)
sys.path.insert(0, os.path.join(os.getenv('ESP_MATTER_PATH'), 'connectedhomeip', 'connectedhomeip', 'scripts', 'tools', 'spake2p'))
from spake2p import generate_verifier
sys.path.insert(0, os.path.join(os.getenv('IDF_PATH'), 'tools', 'mass_mfg'))
from mfg_gen import generate
sys.path.insert(0, os.path.join(os.getenv('ESP_MATTER_PATH'), 'connectedhomeip', 'connectedhomeip', 'src', 'setup_payload', 'python'))
from generate_setup_payload import SetupPayload, CommissioningFlow
TOOLS = {
'spake2p': None,
'chip-cert': None,
'chip-tool': None,
'mfg_gen': None,
}
PAI = {
@@ -67,10 +79,6 @@ UUIDs = list()
def check_tools_exists(args):
TOOLS['spake2p'] = shutil.which('spake2p')
if TOOLS['spake2p'] is None:
logging.error('spake2p not found, please add spake2p path to PATH environment variable')
sys.exit(1)
# if the certs and keys are not in the generated partitions or the specific dac cert and key are used,
# the chip-cert is not needed.
if args.paa or (args.pai and (args.dac_cert is None and args.dac_key is None)):
@@ -79,40 +87,26 @@ def check_tools_exists(args):
logging.error('chip-cert not found, please add chip-cert path to PATH environment variable')
sys.exit(1)
TOOLS['chip-tool'] = shutil.which('chip-tool')
if TOOLS['chip-tool'] is None:
logging.error('chip-tool not found, please add chip-tool path to PATH environment variable')
sys.exit(1)
TOOLS['mfg_gen'] = os.sep.join([os.getenv('IDF_PATH'), 'tools', 'mass_mfg', 'mfg_gen.py'])
if not os.path.exists(TOOLS['mfg_gen']):
logging.error('mfg_gen.py not found, please make sure IDF_PATH environment variable is set correctly')
sys.exit(1)
logging.debug('Using following tools:')
logging.debug('spake2p: {}'.format(TOOLS['spake2p']))
logging.debug('chip-cert: {}'.format(TOOLS['chip-cert']))
logging.debug('chip-tool: {}'.format(TOOLS['chip-tool']))
logging.debug('mfg_gen: {}'.format(TOOLS['mfg_gen']))
def generate_passcodes(args):
iter_count_max = 10000
salt_len_max = 32
cmd = [
TOOLS['spake2p'], 'gen-verifier',
'--count', str(args.count),
'--iteration-count', str(iter_count_max),
'--salt-len', str(salt_len_max),
'--out', OUT_FILE['pin_csv'],
]
# If passcode is provided, use it
if (args.passcode):
cmd.extend(['--pin-code', str(args.passcode)])
execute_cmd(cmd)
with open(OUT_FILE['pin_csv'], 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(["Index", "PIN Code", "Iteration Count", "Salt", "Verifier"])
for i in range(0, args.count):
if args.passcode:
passcode = args.passcode
else:
passcode = random.randint(1, 99999998)
if passcode in INVALID_PASSCODES:
passcode -= 1
salt = os.urandom(salt_len_max)
verifier = generate_verifier(passcode, salt, iter_count_max)
writer.writerow([i, passcode, iter_count_max, base64.b64encode(salt).decode('utf-8'), base64.b64encode(verifier).decode('utf-8')])
def generate_discriminators(args):
@@ -402,33 +396,36 @@ def generate_summary(args):
for row in pin_disc_dict:
pincode = row['PIN Code']
discriminator = row['Discriminator']
qrcode = get_chip_qrcode(TOOLS['chip-tool'], args.vendor_id, args.product_id,
args.commissioning_flow, discriminator, pincode, args.discovery_mode)
manualcode = get_chip_manualcode(TOOLS['chip-tool'], args.vendor_id, args.product_id,
args.commissioning_flow, discriminator, pincode)
payloads = SetupPayload(int(discriminator), int(pincode), 1 << args.discovery_mode, CommissioningFlow(args.commissioning_flow),
args.vendor_id, args.product_id)
qrcode = payloads.generate_qrcode()
manualcode = payloads.generate_manualcode()
summary_csv_data += summary_lines[1 + int(row['Index'])] + ',' + pincode + ',' + qrcode + ',' + manualcode + '\n'
with open(summary_csv, 'w') as scsvf:
scsvf.write(summary_csv_data)
def generate_partitions(suffix, size, encrypt):
cmd = [
'python3', TOOLS['mfg_gen'], 'generate',
OUT_FILE['config_csv'], OUT_FILE['mcsv'],
suffix, hex(size), '--outdir', OUT_DIR['top']
]
partition_args = SimpleNamespace(fileid = None,
version = 2,
inputkey = None,
outdir = OUT_DIR['top'],
conf = OUT_FILE['config_csv'],
values = OUT_FILE['mcsv'],
size = hex(size),
prefix = suffix)
if encrypt:
cmd.append('--keygen')
execute_cmd(cmd)
partition_args.keygen = True
else:
partition_args.keygen = False
generate(partition_args)
def generate_onboarding_data(args, index, discriminator, passcode):
chip_manualcode = get_chip_manualcode(TOOLS['chip-tool'], args.vendor_id, args.product_id,
args.commissioning_flow, discriminator, passcode)
chip_qrcode = get_chip_qrcode(TOOLS['chip-tool'], args.vendor_id, args.product_id,
args.commissioning_flow, discriminator, passcode, args.discovery_mode)
payloads = SetupPayload(discriminator, passcode, 1 << args.discovery_mode, CommissioningFlow(args.commissioning_flow),
args.vendor_id, args.product_id)
chip_qrcode = payloads.generate_qrcode()
chip_manualcode = payloads.generate_manualcode()
logging.info('Generated QR code: ' + chip_qrcode)
logging.info('Generated manual code: ' + chip_manualcode)
+1
View File
@@ -5,3 +5,4 @@ future==0.18.2
pycparser==2.21
pypng==0.0.21
PyQRCode==1.2.1
python_stdnum==1.18
-57
View File
@@ -277,60 +277,3 @@ def execute_cmd(cmd):
logging.error('[stderr]: {}'.format(status.stderr.decode('utf-8').strip()))
logging.error('Command failed with error: {}'.format(e))
sys.exit(1)
def get_manualcode_args(vid, pid, flow, discriminator, passcode):
payload_args = list()
payload_args.append('--discriminator')
payload_args.append(str(discriminator))
payload_args.append('--setup-pin-code')
payload_args.append(str(passcode))
payload_args.append('--version')
payload_args.append('0')
payload_args.append('--vendor-id')
payload_args.append(str(vid))
payload_args.append('--product-id')
payload_args.append(str(pid))
payload_args.append('--commissioning-mode')
payload_args.append(str(flow))
return payload_args
def get_qrcode_args(vid, pid, flow, discriminator, passcode, disc_mode):
payload_args = get_manualcode_args(vid, pid, flow, discriminator, passcode)
payload_args.append('--rendezvous')
payload_args.append(str(1 << disc_mode))
return payload_args
def get_chip_qrcode(chip_tool, vid, pid, flow, discriminator, passcode, disc_mode):
payload_args = get_qrcode_args(vid, pid, flow, discriminator, passcode, disc_mode)
cmd_args = [chip_tool, 'payload', 'generate-qrcode']
cmd_args.extend(payload_args)
data = subprocess.check_output(cmd_args)
# Command output is as below:
# \x1b[0;32m[1655386003372] [23483:7823617] CHIP: [TOO] QR Code: MT:Y.K90-WB010E7648G00\x1b[0m
return data.decode('utf-8').split('QR Code: ')[1][:QRCODE_LEN]
def get_chip_manualcode(chip_tool, vid, pid, flow, discriminator, passcode):
payload_args = get_manualcode_args(vid, pid, flow, discriminator, passcode)
cmd_args = [chip_tool, 'payload', 'generate-manualcode']
cmd_args.extend(payload_args)
data = subprocess.check_output(cmd_args)
# 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 flow else SHORT_MANUALCODE_LEN
ret = data.decode('utf-8').split('Manual Code: ')[1][:manual_code_len]
# For 11-digits manual code, use the format 'XXXX-XXX-XXXX'
# TODO: change the format of 21-digits maunal code
if manual_code_len == SHORT_MANUALCODE_LEN:
ret = ret[:4] + '-' + ret[4:7] + '-' + ret[7:]
return ret