def __init__(self, domain=None, username=None, **kwargs): reg = ComponentRegistry() conf = ConfigManager() if domain is None: domain = conf.get('cloud:server') self.api = Api(domain=domain, **kwargs) self._domain = self.api.domain try: token = reg.get_config('arch:cloud_token') token_type = reg.get_config('arch:cloud_token_type', default='jwt') self.api.set_token(token, token_type=token_type) except ArgumentError: # If we are interactive, try to get the user to login for a single # session rather than making them call link_cloud to store a cloud token if type_system.interactive: username, password = self._prompt_user_pass(username, domain) ok_resp = self.api.login(email=username, password=password) if not ok_resp: raise ExternalError("Could not login to %s as user %s" % (domain, username)) else: raise ExternalError( "No stored iotile cloud authentication information", suggestion= 'Call iotile config link_cloud with your username and password' ) self.token = self.api.token self.token_type = self.api.token_type
def test_nonexistent(): """Make sure nonexistent config vars throw an error """ reg = ComponentRegistry() with pytest.raises(ArgumentError): reg.get_config('test1_nonexistent')
def __init__(self, args): cert = args.get('certificate', None) key = args.get('private_key', None) root = args.get('root_certificate', None) endpoint = args.get('endpoint', None) iamkey = args.get('iam_key', None) iamsecret = args.get('iam_secret', None) iamsession = args.get('iam_session', None) use_websockets = args.get('use_websockets', False) try: if not use_websockets: if cert is None: raise ExternalError("Certificate for AWS IOT not passed in certificate key") elif key is None: raise ExternalError("Private key for certificate not passed in private_key key") else: if iamkey is None or iamsecret is None: raise ExternalError("IAM Credentials need to be provided for websockets auth") except ExternalError: # If the correct information is not passed in, try and see if we get it from our environment # try to pull in root certs, endpoint name and iam or cognito session information reg = ComponentRegistry() if endpoint is None: endpoint = reg.get_config('awsiot-endpoint', default=None) if root is None: root = reg.get_config('awsiot-rootcert', default=None) iamkey = reg.get_config('awsiot-iamkey', default=None) iamsecret = reg.get_config('awsiot-iamtoken', default=None) iamsession = reg.get_config('awsiot-session', default=None) if iamkey is None or iamsecret is None: raise use_websockets = True if root is None: raise ExternalError("Root of certificate chain not passed in root_certificate key (and not in registry)") elif endpoint is None: raise ExternalError("AWS IOT endpoint not passed in endpoint key (and not in registry)") self.websockets = use_websockets self.iam_key = iamkey self.iam_secret = iamsecret self.iam_session = iamsession self.cert = cert self.key = key self.root = root self.endpoint = endpoint self.client = None self.sequencer = TopicSequencer() self.queues = {} self.wildcard_queues = [] self._logger = logging.getLogger(__name__)
def __init__(self, port): super(AWSIOTDeviceAdapter, self).__init__() self.set_config('default_timeout', 5.0) reg = ComponentRegistry() endpoint = reg.get_config('awsiot-endpoint') rootcert = reg.get_config('awsiot-rootcert') iamuser = reg.get_config('awsiot-iamkey') iamsecret = reg.get_config('awsiot-iamtoken') iamsession = reg.get_config('awsiot-session', default=None) args = {} args['endpoint'] = endpoint args['root_certificate'] = rootcert args['use_websockets'] = True args['iam_key'] = iamuser args['iam_secret'] = iamsecret args['iam_session'] = iamsession self._logger = logging.getLogger(__name__) # Port should be a topic prefix that allows us to connect # only to subset of IOTile devices managed by a gateway # rather than to directly accessible iotile devices. if port is None: port = "" if len(port) > 0 and port[-1] != '/': port = port + '/' self.client = OrderedAWSIOTClient(args) self.name = str(uuid.uuid4()) self.client.connect(self.name) self.prefix = port self.conns = ConnectionManager(self.id) self.conns.start() self.client.subscribe(self.prefix + 'devices/+/data/advertisement', self._on_advertisement, ordered=False) self._deferred = queue.Queue() self.set_config('minimum_scan_time', 5.0) self.set_config('probe_supported', True) self.set_config('probe_required', True) self.mtu = self.get_config( 'mtu', 60 * 1024) # Split script payloads larger than this self.report_parser = IOTileReportParser()
def test_create_delete(): """Make sure we can create, fetch and delete config vars """ reg = ComponentRegistry() reg.set_config('test1', 'hello') val = reg.get_config('test1') assert val == 'hello' reg.set_config('test1', 'hello2') val = reg.get_config('test1') assert val == 'hello2' reg.clear_config('test1') with pytest.raises(ArgumentError): reg.get_config('test1')
class ConfigManager(object): """A class for managing typed configuration variables ConfigManager can be used to querying which config variables are defined and to set or get the currently defined variables. """ def __init__(self): self._known_variables = {} self._load_providers() self._load_functions() self._reg = ComponentRegistry() def _load_providers(self): """Load all config_variables providers using pkg_resources """ reg = ComponentRegistry() for name, provider in reg.load_extensions('iotile.config_variables'): try: prefix, conf_vars = provider() except (ValueError, TypeError) as exc: raise ExternalError("Error loading config variables", package=name, error=str(exc)) for var in conf_vars: if len(var) != 3 and len(var) != 4: raise ExternalError( "Error loading config variable, invalid length", data=var, package=name) name = prefix + ':' + var[0] if len(var) == 3: var_obj = ConfigVariable(var[0], var[1], var[2], MISSING) else: var_obj = ConfigVariable(name, var[1], var[2], var[3]) if name in self._known_variables: raise ExternalError( "The same config variable was defined twice", name=name) self._known_variables[name] = var_obj def _load_functions(self): """Load all config functions that should be bound to this ConfigManager Config functions allow you to add functions that will appear under ConfigManager but call your specified function. This is useful for adding complex configuration behavior that is callable from the iotile command line tool """ reg = ComponentRegistry() for _, conf_func in reg.load_extensions('iotile.config_function'): try: name = conf_func.__name__ self.add_function(name, conf_func) except (ValueError, TypeError) as exc: raise ExternalError("Error loading config function", name=name, error=str(exc)) def _format_variable(self, name, var): """Format a helpful string describing a config variable Args: name (string): The prefixed name of the config variable var (ConfigVariable): the variable to format Returns: string: The formatted string in the form name (type): (default %s) description """ if var.default is MISSING: return "%s (%s): %s [no default]" % (name, var.type, var.description) return "%s (%s): %s [default: %s]" % (name, var.type, var.description, var.default) @param("glob", "string", desc="Glob pattern for finding config variables") @return_type("list(string)") def list(self, glob): """List all matching config variables The glob parameter should be a wildcard expression like: build:* to find all config variables defined with a build prefix. Returns: string[]: A list of string descriptions containing descriptions and type information. """ known_vars = [ x for x in sorted(self._known_variables) if fnmatch.fnmatchcase(x, glob) ] return [ '- ' + self._format_variable(x, self._known_variables[x]) for x in known_vars ] @param("name", "string", desc="Config variable to find") @stringable def get(self, name): """Get the current value of a config variable """ if name not in self._known_variables: raise ArgumentError("Unknown config variable", name=name) var = self._known_variables[name] try: val = self._reg.get_config(name) except ArgumentError: if var.default is not MISSING: val = var.default else: raise ArgumentError( "Config variable not set and there is no default value", name=name) typed_val = type_system.convert_to_type(val, var.type) return typed_val @param("name", "string", desc="Config variable to find") @stringable def remove(self, name): """Remove any currently defined values for the named variable """ self._reg.clear_config(name) @param("name", "string", desc="Config variable to set") @param("value", "string", desc="Value to set") def set(self, name, value): """Set the current avlue of a config variable """ if name not in self._known_variables: raise ArgumentError("Unknown config variable", name=name) self._reg.set_config(name, value) @param("name", "string", desc="Config variable to find") @return_type("string") def describe(self, name): """Describe a config variable by name Returns: string: A short description of what the variable is used for """ if name not in self._known_variables: raise ArgumentError("Unknown config variable", name=name) var = self._known_variables[name] return self._format_variable(name, var) def add_variable(self, name, var_type, desc, default=MISSING): """Add a temporary variable to the config variable manager This function is mainly useful for testing since it does not persistently store information about the variable. Args: name (string): The name of the variable var_type (string): The type of the variable. This should be a type known to the type_system. desc (string): The description of what this variable is for default (string): An optional default value for the variable """ self._known_variables[name] = ConfigVariable(name, var_type, desc, default) def add_function(self, name, callable): """Add a config function to the config variable manager Config functions are like config variables but are functions rather than variables. Sometimes you want to expose configuration but you really need a function to actually do it. For example, let's say you want to store a github OAUTH token on behalf of a user. You would like a config function like `link_github` that walks the user through logging in to github and getting a token then you would like to save that token into the config manager like normal. add_function lets you bind a method to ConfigManager dynamically. The function should be a normal function with its first argument as self and it is turned into a bound method on this instance of config manager. Args: name (string): The attribute name for this function callable (callable): A function with first argument self that will be bound to this ConfigManager object as a method. """ if hasattr(self, name): raise ArgumentError( "Trying to add a Config function with a conflicting name", name=name) bound_callable = callable.__get__(self) setattr(self, name, bound_callable)
def watch_broadcasts(self, whitelist=None, blacklist=None): """Spawn an interactive terminal UI to watch broadcast data from devices. Devices are allowed to post a broadcast report containing stream data. This function will create a list in your console window with the latest broadcast value from each device in range. Args: whitelist (list(integer)): Only include devices with these listed ids. blacklist (list(integer)): Include every device **except** those with these specific ids. If combined with whitelist, whitelist wins and this parameter has no effect. """ if self.transport == 'bled112': reg = ComponentRegistry() if reg.get_config('bled112:active-scan') == 'false': self.logger.warning( "Warning: active scan not set, you may not see results") time.sleep(2) if whitelist is not None: whitelist = set(whitelist) if blacklist is not None: blacklist = set(blacklist) def _title(_items): return ["Watching Broadcast Reports (Ctrl-C to Stop)"] def _poll(): results = [x for x in self.iter_broadcast_reports(blocking=False)] return results def _text(item): fmt_uuid = "%08X" % item.origin fmt_uuid = fmt_uuid[:4] + '-' + fmt_uuid[4:] reading = item.visible_readings[0] return "{0: <15} stream: {1: 04X} value: {2: <8}".format( fmt_uuid, reading.stream, reading.value) def _sort_order(item): return item.origin def _hash(item): uuid = item.origin if whitelist is not None and uuid not in whitelist: return None if blacklist is not None and whitelist is None and uuid in blacklist: return None return uuid line_ui = LinebufferUI(_poll, _hash, _text, sortkey_func=_sort_order, title=_title) line_ui.run()