def main(input_config_file=None, input_values_file=None, target_file_name_prefix=None, file_identifier=None, output_dir_path=None, part_size=None, input_version=None, input_is_keygen=None, input_is_encrypt=None, input_is_keyfile=None): try: if all(arg is None for arg in [ input_config_file, input_values_file, target_file_name_prefix, file_identifier, output_dir_path ]): parser = argparse.ArgumentParser( prog='./mfg_gen.py', description= "Create binary files from input config and values file", formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('--conf', dest='config_file', help='the input configuration csv file', default=None) parser.add_argument('--values', dest='values_file', help='the input values csv file', default=None) parser.add_argument('--prefix', dest='prefix', help='the unique name as each filename prefix') parser.add_argument( '--fileid', dest='fileid', help='the unique file identifier(any key in values file) \ as each filename suffix (Default: numeric value(1,2,3...)' ) parser.add_argument( '--outdir', dest='outdir', default=os.getcwd(), help='the output directory to store the files created\ (Default: current directory)') parser.add_argument( "--size", dest='part_size', help='Size of NVS Partition in bytes (must be multiple of 4096)' ) parser.add_argument("--version", dest="version", help='Set version. Default: v2', choices=['v1', 'v2'], default='v2', type=str.lower) parser.add_argument( "--keygen", dest="keygen", help='Generate keys for encryption. Default: false', choices=['true', 'false'], default='false', type=str.lower) parser.add_argument("--encrypt", dest="encrypt", help='Set encryption mode. Default: false', choices=['true', 'false'], default='false', type=str.lower) parser.add_argument( "--keyfile", dest="keyfile", help= 'File having key for encryption (Applicable only if encryption mode is true)', default=None) args = parser.parse_args() args.outdir = os.path.join(args.outdir, '') input_config_file = args.config_file input_values_file = args.values_file target_file_name_prefix = args.prefix output_dir_path = args.outdir part_size = args.part_size input_version = args.version input_is_keygen = args.keygen input_is_encrypt = args.encrypt input_is_keyfile = args.keyfile file_identifier = '' print_arg_str = "Invalid.\nTo generate binary --conf, --values, --prefix and --size arguments are mandatory.\ \nTo generate encryption keys --keygen argument is mandatory." print_encrypt_arg_str = "Missing parameter. Enter --keygen or --keyfile." if args.fileid: file_identifier = args.fileid if input_config_file and input_is_encrypt.lower( ) == 'true' and input_is_keygen.lower( ) == 'true' and input_is_keyfile: sys.exit( 'Invalid. Cannot provide both --keygen and --keyfile argument together.' ) nvs_partition_gen.check_input_args( input_config_file, input_values_file, part_size, input_is_keygen, input_is_encrypt, input_is_keyfile, input_version, print_arg_str, print_encrypt_arg_str, output_dir_path) if not input_config_file and input_is_keygen: if input_is_encrypt == 'true': sys.exit( "Invalid.\nOnly --keyfile and --outdir arguments allowed.\n" ) # Generate Key Only nvs_partition_gen.nvs_part_gen( input_filename=input_config_file, output_filename=input_values_file, input_part_size=part_size, is_key_gen=input_is_keygen, encrypt_mode=input_is_encrypt, key_file=input_is_keyfile, version_no=input_version, output_dir=output_dir_path) exit(0) if not (input_config_file and input_values_file and target_file_name_prefix and part_size): sys.exit(print_arg_str) keys_in_values_file = [] keys_in_config_file = [] config_data_to_write = [] key_value_data = [] csv_file_list = [] keys_repeat = [] is_empty_line = False files_created = False file_identifier_value = '0' output_target_dir = '' target_values_file = None output_file_prefix = None # Verify config file is not empty if os.stat(input_config_file).st_size == 0: raise SystemExit("Oops...config file: %s is empty." % input_config_file) # Verify values file is not empty if os.stat(input_values_file).st_size == 0: raise SystemExit("Oops...values file: %s is empty." % input_values_file) # Verify config file does not have empty lines csv_config_file = open(input_config_file, 'r') try: config_file_reader = csv.reader(csv_config_file, delimiter=',') for config_data in config_file_reader: for data in config_data: empty_line = data.strip() if empty_line is '': is_empty_line = True else: is_empty_line = False break if is_empty_line: raise SystemExit( "Oops...config file: %s cannot have empty lines. " % input_config_file) if not config_data: raise SystemExit( "Oops...config file: %s cannot have empty lines." % input_config_file) csv_config_file.seek(0) # Extract keys from config file for config_data in config_file_reader: if 'namespace' not in config_data: keys_in_config_file.append(config_data[0]) if 'REPEAT' in config_data: keys_repeat.append(config_data[0]) csv_config_file.close() except Exception as e: print(e) finally: csv_config_file.close() is_empty_line = False # Verify values file does not have empty lines csv_values_file = open(input_values_file, 'r') try: values_file_reader = csv.reader(csv_values_file, delimiter=',') for values_data in values_file_reader: for data in values_data: empty_line = data.strip() if empty_line is '': is_empty_line = True else: is_empty_line = False break if is_empty_line: raise SystemExit( "Oops...values file: %s cannot have empty lines." % input_values_file) if not values_data: raise SystemExit( "Oops...values file: %s cannot have empty lines." % input_values_file) csv_values_file.seek(0) # Extract keys from values file keys_in_values_file = next(values_file_reader) csv_values_file.close() except Exception as e: print(e) exit(1) finally: csv_values_file.close() # Verify file identifier exists in values file if file_identifier: if file_identifier not in keys_in_values_file: raise SystemExit( 'Oops...target_file_identifier: %s does not exist in values file.\n' % file_identifier) # Verify data in the input_config_file and input_values_file verify_data_in_file(input_config_file, input_values_file, keys_in_config_file, keys_in_values_file, keys_repeat) # Add config data per namespace to `config_data_to_write` list config_data_to_write = add_config_data_per_namespace(input_config_file) try: with open(input_values_file, 'r') as csv_values_file: values_file_reader = csv.reader(csv_values_file, delimiter=',') keys = next(values_file_reader) filename, file_ext = os.path.splitext(input_values_file) target_filename = filename + "_created" + file_ext if keys_repeat: target_values_file = set_repeat_value(keys_repeat, keys, input_values_file, target_filename) else: target_values_file = input_values_file csv_values_file = open(target_values_file, 'r') values_file_reader = csv.reader(csv_values_file, delimiter=',') next(values_file_reader) for values_data_line in values_file_reader: key_value_data = list( zip_longest(keys_in_values_file, values_data_line)) # Get file identifier value from values file file_identifier_value = get_fileid_val( file_identifier, keys_in_config_file, keys_in_values_file, values_data_line, key_value_data, file_identifier_value) key_value_pair = key_value_data[:] # Create new directory(if doesn't exist) to store csv file generated output_target_dir = create_dir("csv/", output_dir_path) # Verify if output csv file does not exist csv_filename = target_file_name_prefix + "-" + file_identifier_value + ".csv" csv_file_list.append(csv_filename) output_csv_file = output_target_dir + csv_filename if os.path.isfile(output_csv_file): raise SystemExit("Target csv file: %s already exists.`" % output_csv_file) # Add values corresponding to each key to csv target file add_data_to_file(config_data_to_write, key_value_pair, output_csv_file) # Create new directory(if doesn't exist) to store bin file generated output_target_dir = create_dir("bin/", output_dir_path) # Verify if output bin file does not exist output_file_prefix = target_file_name_prefix + "-" + file_identifier_value output_bin_file = output_target_dir + output_file_prefix + ".bin" if os.path.isfile(output_bin_file): raise SystemExit("Target csv file: %s already exists.`" % output_bin_file) # Create output csv and bin file if input_is_keygen.lower() == 'true' and input_is_keyfile: input_is_keyfile = os.path.basename(input_is_keyfile) nvs_partition_gen.nvs_part_gen( input_filename=output_csv_file, output_filename=output_bin_file, input_part_size=part_size, is_key_gen=input_is_keygen, encrypt_mode=input_is_encrypt, key_file=input_is_keyfile, version_no=input_version, encr_key_prefix=output_file_prefix, output_dir=output_dir_path) print("CSV Generated: ", str(output_csv_file)) files_created = True csv_values_file.close() except Exception as e: print(e) exit(1) finally: csv_values_file.close() return csv_file_list, files_created, target_values_file except ValueError as err: print(err) except Exception: raise
def main(): try: parser = argparse.ArgumentParser(prog='./factory_nvs_gen.py',\ description="Factory NVS Generator",\ formatter_class=argparse.RawDescriptionHelpFormatter) factory_nvs_part_gen_group = parser.add_argument_group('To generate Factory NVS partition') factory_nvs_part_gen_group.add_argument('setup_code',\ help='the input setup code without hyphens Eg.: 11122333 ') factory_nvs_part_gen_group.add_argument('setup_id',\ help='the input setup identifer Eg.: ES32') factory_nvs_part_gen_group.add_argument('--infile',dest='infile',\ help='the input csv file with extension(full path) to add HomeKit data generated to this file Eg.: fan_data.csv') factory_nvs_part_gen_group.add_argument('outfile',\ help='the output csv and bin filename without extension Eg.: fan_factory') factory_nvs_part_gen_group.add_argument('--size', \ help='Size of NVS Partition in bytes (must be multiple of 4096)', \ default='0x4000') factory_nvs_part_gen_group.add_argument('--version', \ help='Set version. Default: v2',choices=['v1','v2'], \ default='v2',type=str.lower) factory_nvs_part_gen_group.add_argument("--keygen", \ help='Generate keys for encryption. Creates an `encryption_keys.bin` file. Default: false', \ choices=['true','false'],default= 'false',type=str.lower) factory_nvs_part_gen_group.add_argument("--encrypt", \ help='Set encryption mode. Default: false', \ choices=['true','false'],default='false',type=str.lower) factory_nvs_part_gen_group.add_argument("--keyfile", \ help='File having key for encryption (Applicable only if encryption mode is true)', default = None) factory_nvs_part_gen_group.add_argument('--outdir', dest='outdir', \ help='the output directory to store the files created(Default: current directory)', default=os.getcwd()) factory_nvs_part_gen_group.add_argument('--salt', \ help='Predefined salt if any', \ default=None) args = parser.parse_args() part_size = args.size is_key_gen = args.keygen encrypt_mode = args.encrypt version_no = args.version key_file = args.keyfile output_dir_path = args.outdir salt_input = args.salt # Check if the setup code has valid format setup_code = args.setup_code if (len(setup_code) != 8) or (not setup_code.isdigit()): print("Setup code should be 8 numbers without any '-' in between. Eg. 11122333") sys.exit (1) # Add the hyphen (-) in the PIN for salt-verifier generation. So, 11122333 will become 111-22-333 setup_code = setup_code[:3] + '-' + setup_code[3:5] + '-' + setup_code[5:] setup_id = args.setup_id file_prefix = args.outfile if not args.infile: csv_file = file_prefix + ".csv" else: if not os.path.isfile(args.infile): sys.exit("Oops...file: `" + args.infile + "` does not exist...") else: csv_file = file_prefix + ".csv" bin_file = file_prefix + ".bin" # Consider enabling RFC5054 compatibility for interoperation with non srp SRP-6a implementations #srp.rfc5054_enable() # The Modulus, N, and Generator, g, as specified by the 3072-bit group of RFC5054. This is required since the standard srp script does not support this n_3072 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" g_3072 = "5" # Generate the Salt and Verifier for the given PIN salt, vkey = srp.create_salted_verification_key( 'Pair-Setup', setup_code, srp.SHA512, srp.NG_CUSTOM, n_3072, g_3072, salt_len=16 , salt=salt_input) # Create the CSV file with appropriate data f = open(csv_file, 'w') if not args.infile: f.write("key,type,encoding,value\n") else: in_f = open(args.infile, 'r') data = in_f.read() f.write(data) in_f.close() f.close() hap_setup_found = False f = open(csv_file,'a+') f.seek(0) f_reader = csv.reader(f, delimiter='\n') for data in f_reader: if 'hap_setup,namespace,,' in data: hap_setup_found = True break if not hap_setup_found: f.write("hap_setup,namespace,,\n") f.write("setup_id,data,binary," + setup_id + "\n") f.write("setup_salt,data,hex2bin," + binascii.b2a_hex(salt).zfill(32).decode("utf-8") + "\n") f.write("setup_verifier,data,hex2bin," + binascii.b2a_hex(vkey).zfill(768).decode("utf-8")) f.close() print("CSV Generated: " + csv_file) print_arg_str = "Invalid.\nTo generate nvs partition binary --input, --output and --size arguments are mandatory.\nTo generate encryption keys --keygen argument is mandatory." print_encrypt_arg_str = "Missing parameter. Enter --keyfile or --keygen." nvs_partition_gen.check_input_args(csv_file, bin_file, part_size, is_key_gen,\ encrypt_mode, key_file, version_no, print_arg_str, print_encrypt_arg_str, output_dir_path) nvs_partition_gen.nvs_part_gen(input_filename=csv_file, output_filename=bin_file,\ input_part_size=part_size, is_key_gen=is_key_gen,\ encrypt_mode=encrypt_mode, key_file=key_file,\ encr_key_prefix=None, version_no=version_no, output_dir=output_dir_path) print("NVS Flash Binary Generated: " + bin_file) except Exception as e: sys.exit(e)
def main(): try: filename = os.path.join('.', 'hk_mfg_gen.py') parser = argparse.ArgumentParser( prog=filename, description= "Generate HomeKit specific data and create binaries and HomeKit setup info", formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('--conf', dest='config_file', help='the input configuration csv file') parser.add_argument( '--values', dest='values_file', help='the input values csv file (the number of accessories \ to create HomeKit data for is equal to the data entries \ in this file)', default=None) parser.add_argument('--prefix', dest='prefix', help='the accessory name as each filename prefix', default=None) parser.add_argument( '--fileid', dest='fileid', help='the unique file identifier(any key in values file) as \ each filename suffix (Default: setup_code)', default=None) curr_dir = os.path.join('.', '') parser.add_argument( '--outdir', dest='outdir', default=curr_dir, help='the output directory to store the files created \ (Default: current directory)') parser.add_argument('--cid', dest='cid', type=int, help='the accessory category identifier', default=None) parser.add_argument( '--count', dest='count', type=int, help='the number of accessories to create HomeKit data for,\ applicable only if --values is not given', default=None) parser.add_argument( "--size", dest='part_size', help='Size of NVS Partition in bytes (must be multiple of 4096)', default=None) parser.add_argument("--version", dest="version", help='Set version. Default: v2', choices=['v1', 'v2'], default='v2', type=str.lower) parser.add_argument( "--keygen", dest="keygen", help='Generate keys for encryption. Default: False', choices=['true', 'false'], default='false', type=str.lower) parser.add_argument("--encrypt", dest="encrypt", help='Set encryption mode. Default: False', choices=['true', 'false'], default='false', type=str.lower) parser.add_argument( "--keyfile", dest="keyfile", help= 'File having key for encryption (Applicable only if encryption mode is true)', default=None) args = parser.parse_args() input_config_file = args.config_file input_values_file = args.values_file input_prefix = args.prefix input_fileid = args.fileid input_outdir = args.outdir input_cid = args.cid input_count = args.count part_size = args.part_size version = args.version input_is_keygen = args.keygen input_is_encrypt = args.encrypt input_is_keyfile = args.keyfile GENERATE_KEY_ONLY = False print_arg_str = "\nTo generate nvs partition binary with custom data --conf, --values, --prefix --cid, and --size arguments are mandatory.\ \nTo generate nvs partition binary without any custom data --count, --prefix --cid, and --size arguments are mandatory.\ \nTo generate encryption keys --keygen argument is mandatory." print_encrypt_arg_str = "Missing parameter. Enter --keyfile." if not part_size and input_is_keygen.lower() == 'true': if input_is_encrypt == 'true': sys.exit( "Invalid.\nOnly --keyfile and --outdir arguments allowed.\n" ) GENERATE_KEY_ONLY = True nvs_partition_gen.check_input_args(input_config_file, input_values_file, part_size, input_is_keygen,\ input_is_encrypt, input_is_keyfile, version, print_arg_str, print_encrypt_arg_str, input_outdir) nvs_partition_gen.nvs_part_gen(input_filename = input_config_file, output_filename = input_values_file,\ input_part_size=part_size, is_key_gen=input_is_keygen,\ encrypt_mode=input_is_encrypt, key_file=input_is_keyfile,\ version_no=version, output_dir=input_outdir) sys.exit(0) # Verify that --cid argument and --prefix arguments are given if not input_cid or not input_prefix: parser.error(print_arg_str) # Verify that --values argument and --count argument are not given together if input_values_file and input_count: parser.error('--values and --count cannot be given together') # Verify if --fileid argument is given then --values argument should also be given if input_fileid and not input_values_file: parser.error('--values is needed as --fileid given') # Verify --count argument is given if --values file is not given if not input_config_file: if not input_values_file and not input_count: parser.error('--count or --values is needed') else: # Verify that --conf argument and --count argument are not given together if input_count: parser.error('--conf and --count cannot be given together') # Verify if --conf argument is given then --values argument should also be given if not input_values_file: parser.error('--values is needed as --conf given') # Add backslash to outdir if it is not present backslash = ['/', '\\'] if not any(ch in input_outdir for ch in backslash): input_outdir = os.path.join(args.outdir, '') # Set default value for fileid if --fileid argument is not given if not input_fileid: input_fileid = 'setup_code' if input_is_encrypt.lower() == 'true': if input_is_keygen.lower() == 'true' and input_is_keyfile: parser.error( 'Invalid. Cannot provide --keygen and --keyfile with --encrypt argument.' ) #else: # parser.error('Invalid. --keyfile needed as --encrypt is True.') elif not (input_is_keygen.lower() == 'true' or input_is_keyfile): parser.error( 'Invalid. Must provide --keygen or --keyfile with --encrypt argument.' ) if input_count: nvs_partition_gen.check_input_args("None", "None", part_size, input_is_keygen,\ input_is_encrypt, input_is_keyfile, version, print_arg_str, print_encrypt_arg_str, input_outdir) else: nvs_partition_gen.check_input_args(input_config_file, input_values_file, part_size, input_is_keygen,\ input_is_encrypt, input_is_keyfile, version, print_arg_str, print_encrypt_arg_str, input_outdir) setup_id_created = [] setup_code_created = [] salt_created = [] vkey_created = [] keys_in_values_file = [] keys_in_config_file = [] values_file_keys = [] homekit_data = [] data_in_values_file = [] csv_output_filenames = [] setup_payload = b'' setup_code = b'' is_empty_line = False files_created = False total_value_count = 1 hk_setup_info_dir = os.path.join('homekit_setup_info', '') if input_config_file: # Verify config file is not empty if os.stat(input_config_file).st_size == 0: raise SystemExit("Oops...config file: %s is empty..." % input_config_file) # Verify config file does not have empty lines config_file = open(input_config_file, 'r') config_file_reader = csv.reader(config_file, delimiter=',') for config_data in config_file_reader: for data in config_data: empty_line = data.strip() if empty_line is '': is_empty_line = True else: is_empty_line = False break if is_empty_line: raise SystemExit( "Oops...config file: %s cannot have empty lines..." % input_config_file) if not config_data: raise SystemExit( "Oops...config file: %s cannot have empty lines..." % str(input_config_file)) config_file.close() # Extract keys from config file config_file = open(input_config_file, 'r') config_file_reader = csv.reader(config_file, delimiter=',') for config_data in config_file_reader: if not 'namespace' in config_data: keys_in_config_file.append(config_data[0]) config_file.close() # Verify data in the input config file verify_data_in_file(input_config_file=input_config_file) is_empty_line = False if input_values_file: # Verify values file is not empty if os.stat(input_values_file).st_size == 0: raise SystemExit("Oops...values file: %s is empty..." % input_values_file) # Verify values file does not have empty lines csv_values_file = open(input_values_file, 'r') values_file_reader = csv.reader(csv_values_file, delimiter=',') for values_data in values_file_reader: for data in values_data: empty_line = data.strip() if empty_line is '': is_empty_line = True else: is_empty_line = False break if is_empty_line is True: raise SystemExit( "Oops...values file: %s cannot have empty lines..." % input_values_file) if not values_data: raise SystemExit( "Oops...values file: %s cannot have empty lines..." % str(input_values_file)) csv_values_file.close() # Extract keys from values file values_file = open(input_values_file, 'r') values_file_reader = csv.reader(values_file, delimiter=',') keys_in_values_file = next(values_file_reader) values_file.close() values_file = open(input_values_file, 'r') values_file_reader = csv.reader(values_file, delimiter=',') next(values_file_reader) # Verify file identifier exists in values file if 'setup_code' not in input_fileid: if input_fileid not in keys_in_values_file: raise SystemExit( 'Oops...target_file_id: %s does not exist in values file...\n' % input_fileid) # Verify data in the input values_file verify_data_in_file(input_values_file=input_values_file, keys_in_values_file=keys_in_values_file) # Add data in values file to list for values in values_file_reader: data_in_values_file.append(values) # Get number of rows from values file which is equal to\ # the number of accessories to create HomeKit data for total_value_count = len(data_in_values_file) values_file.close() if input_config_file and input_values_file: # Get keys from values file present in config files values_file_keys = get_keys(keys_in_values_file, keys_in_config_file) # Verify data in the input values_file verify_data_in_file(input_config_file=input_config_file, keys_in_values_file=values_file_keys) if input_values_file: keys_in_values_file.extend([ 'setup_id', 'setup_code', 'setup_salt', 'setup_verifier', 'setup_payload' ]) else: keys_in_values_file = [ 'setup_id', 'setup_code', 'setup_salt', 'setup_verifier', 'setup_payload' ] # Generate homekit data if input_count: setup_id_created, setup_code_created, salt_created, vkey_created = homekit_data_gen( no_of_accessories=input_count) else: setup_id_created, setup_code_created, salt_created, vkey_created = homekit_data_gen( no_of_accessories=total_value_count) # Verify Accessory Category Identifier (cid) setup_info_gen.verify_cid(input_cid) # Generate setup payload and add it alongwith the homekit data generated to config and values file(if exist)\ # if input config and input values file do not exist then new files are created if data_in_values_file: for (values, setup_id, setup_code, salt, vkey) in \ list(zip_longest(data_in_values_file,setup_id_created,setup_code_created,\ salt_created, vkey_created)): setup_payload,setup_code = setup_info_gen.setup_payload_create(input_cid,\ setup_code=setup_code,setup_id=setup_id) values.extend( [setup_id, setup_code, salt, vkey, setup_payload]) homekit_data.append(values) else: for (setup_id, setup_code, salt, vkey) in \ list(zip_longest(setup_id_created,setup_code_created,\ salt_created, vkey_created)): setup_payload,setup_code = setup_info_gen.setup_payload_create(input_cid,\ setup_code=setup_code,setup_id=setup_id) homekit_data.append( [setup_id, setup_code, salt, vkey, setup_payload]) target_config_file,target_values_file = add_homekit_data_to_file(input_config_file, \ input_values_file, keys_in_values_file, homekit_data, input_outdir) # Generate csv and bin file csv_output_filenames, files_created, target_values_file = mfg_gen.main(input_config_file=target_config_file, input_values_file=target_values_file,\ target_file_name_prefix=input_prefix, file_identifier=input_fileid,\ output_dir_path=input_outdir, part_size=part_size,\ input_version=version, input_is_keygen=input_is_keygen,\ input_is_encrypt=input_is_encrypt ,input_is_keyfile=input_is_keyfile) print("HomeKit config data generated is added to file: ", target_config_file) print("HomeKit values data generated is added to file: ", target_values_file) if not files_created: raise SystemExit( "Oops...csv,bin,setup info files could not be created...Please check your input files..." ) # Create new directory(if doesn't exist) to store homekit setup info generated output_target_dir = input_outdir + hk_setup_info_dir if not os.path.isdir(output_target_dir): distutils.dir_util.mkpath(output_target_dir) # Write homekit setup info generated to output_target_file write_homekit_setup_info(target_values_file, output_target_dir, csv_output_filenames) except Exception as std_err: print(std_err) except: raise
def main(input_config_file=None,input_values_file=None,target_file_name_prefix=None, file_identifier=None,output_dir_path=None,part_size=None,input_version=None, input_is_keygen=None,input_is_encrypt=None,input_is_keyfile=None): try: if all(arg is None for arg in [input_config_file,input_values_file,target_file_name_prefix, file_identifier,output_dir_path]): parser = argparse.ArgumentParser(prog='./mfg_gen.py', description="Create binary files from input config and values file", formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('--conf', dest='config_file', help='the input configuration csv file', default=None) parser.add_argument('--values', dest='values_file', help='the input values csv file', default=None) parser.add_argument('--prefix', dest='prefix', help='the unique name as each filename prefix') parser.add_argument('--fileid', dest='fileid', help='the unique file identifier(any key in values file) \ as each filename suffix (Default: numeric value(1,2,3...)') parser.add_argument('--outdir', dest='outdir', default=os.getcwd(), help='the output directory to store the files created\ (Default: current directory)') parser.add_argument("--size", dest='part_size', help='Size of NVS Partition in bytes (must be multiple of 4096)') parser.add_argument("--version", dest="version", help='Set version. Default: v2', choices=['v1','v2'], default='v2', type=str.lower) parser.add_argument("--keygen", dest="keygen", help='Generate keys for encryption. Default: false', choices=['true','false'], default='false', type=str.lower) parser.add_argument("--encrypt", dest="encrypt", help='Set encryption mode. Default: false', choices=['true','false'], default='false', type=str.lower) parser.add_argument("--keyfile", dest="keyfile", help='File having key for encryption (Applicable only if encryption mode is true)', default=None) args = parser.parse_args() args.outdir = os.path.join(args.outdir, '') input_config_file = args.config_file input_values_file = args.values_file target_file_name_prefix = args.prefix output_dir_path = args.outdir part_size = args.part_size input_version = args.version input_is_keygen = args.keygen input_is_encrypt = args.encrypt input_is_keyfile = args.keyfile file_identifier = '' print_arg_str = "Invalid.\nTo generate binary --conf, --values, --prefix and --size arguments are mandatory.\ \nTo generate encryption keys --keygen argument is mandatory." print_encrypt_arg_str = "Missing parameter. Enter --keygen or --keyfile." if args.fileid: file_identifier = args.fileid if input_config_file and input_is_encrypt.lower() == 'true' and input_is_keygen.lower() == 'true' and input_is_keyfile: sys.exit('Invalid. Cannot provide both --keygen and --keyfile argument together.') nvs_partition_gen.check_input_args(input_config_file, input_values_file, part_size, input_is_keygen, input_is_encrypt, input_is_keyfile, input_version, print_arg_str, print_encrypt_arg_str, output_dir_path) if not input_config_file and input_is_keygen: if input_is_encrypt == 'true': sys.exit("Invalid.\nOnly --keyfile and --outdir arguments allowed.\n") # Generate Key Only nvs_partition_gen.nvs_part_gen(input_filename=input_config_file, output_filename=input_values_file, input_part_size=part_size, is_key_gen=input_is_keygen, encrypt_mode=input_is_encrypt, key_file=input_is_keyfile, version_no=input_version, output_dir=output_dir_path) exit(0) if not (input_config_file and input_values_file and target_file_name_prefix and part_size): sys.exit(print_arg_str) keys_in_values_file = [] keys_in_config_file = [] config_data_to_write = [] key_value_data = [] csv_file_list = [] keys_repeat = [] is_empty_line = False files_created = False file_identifier_value = '0' output_target_dir = '' target_values_file = None output_file_prefix = None # Verify config file is not empty if os.stat(input_config_file).st_size == 0: raise SystemExit("Oops...config file: %s is empty." % input_config_file) # Verify values file is not empty if os.stat(input_values_file).st_size == 0: raise SystemExit("Oops...values file: %s is empty." % input_values_file) # Verify config file does not have empty lines csv_config_file = open(input_config_file,'r') try: config_file_reader = csv.reader(csv_config_file, delimiter=',') for config_data in config_file_reader: for data in config_data: empty_line = data.strip() if empty_line is '': is_empty_line = True else: is_empty_line = False break if is_empty_line: raise SystemExit("Oops...config file: %s cannot have empty lines. " % input_config_file) if not config_data: raise SystemExit("Oops...config file: %s cannot have empty lines." % input_config_file) csv_config_file.seek(0) # Extract keys from config file for config_data in config_file_reader: if 'namespace' not in config_data: keys_in_config_file.append(config_data[0]) if 'REPEAT' in config_data: keys_repeat.append(config_data[0]) csv_config_file.close() except Exception as e: print(e) finally: csv_config_file.close() is_empty_line = False # Verify values file does not have empty lines csv_values_file = open(input_values_file, 'r') try: values_file_reader = csv.reader(csv_values_file, delimiter=',') for values_data in values_file_reader: for data in values_data: empty_line = data.strip() if empty_line is '': is_empty_line = True else: is_empty_line = False break if is_empty_line: raise SystemExit("Oops...values file: %s cannot have empty lines." % input_values_file) if not values_data: raise SystemExit("Oops...values file: %s cannot have empty lines." % input_values_file) csv_values_file.seek(0) # Extract keys from values file keys_in_values_file = next(values_file_reader) csv_values_file.close() except Exception as e: print(e) exit(1) finally: csv_values_file.close() # Verify file identifier exists in values file if file_identifier: if file_identifier not in keys_in_values_file: raise SystemExit('Oops...target_file_identifier: %s does not exist in values file.\n' % file_identifier) # Verify data in the input_config_file and input_values_file verify_data_in_file(input_config_file, input_values_file, keys_in_config_file, keys_in_values_file, keys_repeat) # Add config data per namespace to `config_data_to_write` list config_data_to_write = add_config_data_per_namespace(input_config_file) try: with open(input_values_file, 'r') as csv_values_file: values_file_reader = csv.reader(csv_values_file, delimiter=',') keys = next(values_file_reader) filename, file_ext = os.path.splitext(input_values_file) target_filename = filename + "_created" + file_ext if keys_repeat: target_values_file = set_repeat_value(keys_repeat, keys, input_values_file, target_filename) else: target_values_file = input_values_file csv_values_file = open(target_values_file, 'r') values_file_reader = csv.reader(csv_values_file, delimiter=',') next(values_file_reader) for values_data_line in values_file_reader: key_value_data = list(zip_longest(keys_in_values_file,values_data_line)) # Get file identifier value from values file file_identifier_value = get_fileid_val(file_identifier, keys_in_config_file, keys_in_values_file, values_data_line, key_value_data, file_identifier_value) key_value_pair = key_value_data[:] # Create new directory(if doesn't exist) to store csv file generated output_target_dir = create_dir("csv/", output_dir_path) # Verify if output csv file does not exist csv_filename = target_file_name_prefix + "-" + file_identifier_value + ".csv" csv_file_list.append(csv_filename) output_csv_file = output_target_dir + csv_filename if os.path.isfile(output_csv_file): raise SystemExit("Target csv file: %s already exists.`" % output_csv_file) # Add values corresponding to each key to csv target file add_data_to_file(config_data_to_write, key_value_pair, output_csv_file) # Create new directory(if doesn't exist) to store bin file generated output_target_dir = create_dir("bin/", output_dir_path) # Verify if output bin file does not exist # todo for keys output_file_prefix = target_file_name_prefix + "-" + file_identifier_value output_bin_file = output_target_dir + output_file_prefix + ".bin" if os.path.isfile(output_bin_file): raise SystemExit("Target csv file: %s already exists.`" % output_bin_file) # Create output csv and bin file if input_is_keygen.lower() == 'true' and input_is_keyfile: input_is_keyfile = os.path.basename(input_is_keyfile) nvs_partition_gen.nvs_part_gen(input_filename=output_csv_file, output_filename=output_bin_file, input_part_size=part_size, is_key_gen=input_is_keygen, encrypt_mode=input_is_encrypt, key_file=input_is_keyfile, version_no=input_version, encr_key_prefix=output_file_prefix, output_dir=output_dir_path) print("CSV Generated: ", str(output_csv_file)) files_created = True csv_values_file.close() except Exception as e: print(e) exit(1) finally: csv_values_file.close() return csv_file_list, files_created, target_values_file except ValueError as err: print(err) except Exception: raise