import json import click from pathlib import Path import logging import re from iottb import definitions from iottb.models.device_metadata import DeviceMetadata from iottb.models.iottb_config import IottbConfig from iottb.definitions import CFG_FILE_PATH, TB_ECHO_STYLES logger = logging.getLogger(__name__) def add_device_guided(ctx, cn, db): click.echo('TODO: Implement') logger.info('Adding device interactively') # logger.debug(f'Parameters: {params}. value: {value}') @click.command('add-device', help='Add a device to a database') @click.argument('device', type=str, required=True) @click.option('--db', '--database', type=click.Path(exists=True, file_okay=False, dir_okay=True), envvar='IOTTB_DB', show_envvar=True, help='Database in which to add this device. If not specified use default from config.') @click.option('--guided', is_flag=True, default=False, show_default=True, envvar='IOTTB_GUIDED_ADD', show_envvar=True, help='Add device interactively') def add_device(dev, db, guided): """Add a new device to a database Device name must be supplied unless in an interactive setup. Database is taken from config by default. If this device name contains spaces or other special characters normalization is performed to derive a canonical name. """ logger.info('add-device invoked') # Step 1: Load Config # Dependency: Config file must exist config = IottbConfig(Path(CFG_FILE_PATH)) logger.debug(f'Config loaded: {config}') # Step 2: Load database # dependency: Database folder must exist if db: database = db path = config.db_path_dict[database] logger.debug(f'Resolved (path, db) {path}, {database}') else: path = config.default_db_location database = config.default_database logger.debug(f'Default (path, db) {path}, {database}') click.secho(f'Using database {database}') full_db_path = Path(path) / database if not full_db_path.is_dir(): logger.warning(f'No database at {database}') click.echo(f'No database found at {full_db_path}', lvl='w') click.echo( f'You need to initialize the testbed before before you add devices!') click.echo( f'To initialize the testbed in the default location run "iottb init-db"') click.echo('Exiting...') exit() # Step 3: Check if device already exists in database # dependency: DeviceMetadata object device_metadata = DeviceMetadata(device_name=dev) device_dir = full_db_path / device_metadata.canonical_name # Check if device is already registered if device_dir.exists(): logger.warning(f'Device directory {device_dir} already exists.') click.echo(f'Device {dev} already exists in the database.') click.echo('Exiting...') exit() try: device_dir.mkdir() except OSError as e: logger.error(f'Error trying to create device {e}') click.echo('Exiting...') exit() # Step 4: Save metadata into device_dir metadata_path = device_dir / definitions.DEVICE_METADATA_FILE_NAME with metadata_path.open('w') as metadata_file: json.dump(device_metadata.__dict__, metadata_file, indent=4) click.echo(f'Successfully added device {dev} to database') logger.debug(f'Added device {dev} to database { database}. Full path of metadata {metadata_path}') logger.info(f'Metadata for {dev} {device_metadata.print_attributes()}')