def listcmd(ctx: Configuration, devicefilter: str): """List all devices from Home Assistant.""" ctx.auto_output("table") devices = api.get_devices(ctx) result = [] # type: List[Dict] if devicefilter == ".*": result = devices else: devicefilterre = re.compile(devicefilter) # type: Pattern for device in devices: if devicefilterre.search(device['name']): result.append(device) cols = [ ('ID', 'id'), ('NAME', 'name'), ('MODEL', 'model'), ('MANUFACTURER', 'manufacturer'), ('AREA', 'area_id'), ] ctx.echo( helper.format_output( ctx, result, columns=ctx.columns if ctx.columns else cols ) )
def listcmd(ctx: Configuration, entityfilter: str): """List all entities from Home Assistant.""" ctx.auto_output("table") entities = api.get_entities(ctx) result = [] # type: List[Dict] if entityfilter == ".*": result = entities else: entityfilterre = re.compile(entityfilter) # type: Pattern for entity in entities: if entityfilterre.search(entity['entity_id']): result.append(entity) cols = [ ('ENTITY_ID', 'entity_id'), ('NAME', 'name'), ('DEVICE_ID', 'device_id'), ('PLATFORM', 'platform'), ('CONFIG_ENTRY_ID', 'config_entry_id'), ('DISABLED_BY', 'disabled_by'), ] ctx.echo( helper.format_output( ctx, result, columns=ctx.columns if ctx.columns else cols ) )
def listcmd(ctx: Configuration, entityfilter: str): """List all entities from Home Assistant.""" ctx.auto_output("table") entities = api.get_entities(ctx) result = [] # type: List[Dict] if entityfilter == ".*": result = entities else: entityfilterre = re.compile(entityfilter) # type: Pattern for entity in entities: if entityfilterre.search(entity['entity_id']): result.append(entity) cols = [ ('ENTITY_ID', 'entity_id'), ('NAME', 'name'), ('DEVICE_ID', 'device_id'), ('PLATFORM', 'platform'), ('CONFIG_ENTRY_ID', 'config_entry_id'), ('DISABLED_BY', 'disabled_by'), ] ctx.echo( helper.format_output(ctx, result, columns=ctx.columns if ctx.columns else cols))
def get(ctx: Configuration, entity): """Get/read entity state from Home Assistant.""" ctx.auto_output("table") state = api.get_state(ctx, entity) if state: ctx.echo(helper.format_output(ctx, [state], const.COLUMNS_ENTITIES)) else: _LOGGING.error("Entity with id: '%s' not found.", entity)
def _report(ctx: Configuration, result: List[Dict[str, Any]], action: str): ctx.echo( helper.format_output( ctx, result, columns=ctx.columns if ctx.columns else const.COLUMNS_ENTITIES, )) if ctx.verbose: ctx.echo("%s entities reported to be %s", len(result), action)
def health(ctx: Configuration): """Get system health from Home Assistant.""" info = api.get_health(ctx) ctx.echo( format_output( ctx, [info], columns=ctx.columns if ctx.columns else const.COLUMNS_DEFAULT, ))
def _report(ctx: Configuration, result: List[Dict[str, Any]], action: str): ctx.echo( helper.format_output( ctx, result, columns=ctx.columns if ctx.columns else const.COLUMNS_ENTITIES, ) ) if ctx.verbose: ctx.echo("%s entities reported to be %s", len(result), action)
def history(ctx: Configuration, entities: List, since: str, end: str): """Get history from Home Assistant, all or per entity. You can use `--since` and `--end` to narrow or expand the time period. Both options accepts a full timestamp i.e. `2016-02-06T22:15:00+00:00` or a relative expression i.e. `3m` for three minutes, `5d` for 5 days. Even `3 minutes` or `5 days` will work. See https://dateparser.readthedocs.io/en/latest/#features for examples. """ import dateparser ctx.auto_output("table") settings = { 'DATE_ORDER': 'DMY', 'TIMEZONE': 'UTC', 'RETURN_AS_TIMEZONE_AWARE': True, } start_time = dateparser.parse(since, settings=settings) end_time = dateparser.parse(end, settings=settings) delta = end_time - start_time if ctx.verbose: click.echo( 'Querying from {}:{} to {}:{} a span of {}'.format( since, start_time.isoformat(), end, end_time.isoformat(), delta ) ) data = api.get_history(ctx, list(entities), start_time, end_time) result = [] # type: List[Dict[str, Any]] entitycount = 0 for item in data: result.extend(item) # type: ignore entitycount = entitycount + 1 click.echo( helper.format_output( ctx, result, columns=ctx.columns if ctx.columns else const.COLUMNS_ENTITIES, ) ) if ctx.verbose: click.echo( 'History with {} rows from {} entities found.'.format( len(result), entitycount ) )
def history(ctx: Configuration, entities: List, since: str, end: str): """Get state history from Home Assistant, all or per entity. You can use `--since` and `--end` to narrow or expand the time period. Both options accepts a full timestamp i.e. `2016-02-06T22:15:00+00:00` or a relative expression i.e. `3m` for three minutes, `5d` for 5 days. Even `3 minutes` or `5 days` will work. See https://dateparser.readthedocs.io/en/latest/#features for examples. """ import dateparser ctx.auto_output("table") settings = { 'DATE_ORDER': 'DMY', 'TIMEZONE': 'UTC', 'RETURN_AS_TIMEZONE_AWARE': True, } start_time = dateparser.parse(since, settings=settings) end_time = dateparser.parse(end, settings=settings) delta = end_time - start_time if ctx.verbose: click.echo( 'Querying from {}:{} to {}:{} a span of {}'.format( since, start_time.isoformat(), end, end_time.isoformat(), delta ) ) data = api.get_history(ctx, list(entities), start_time, end_time) result = [] # type: List[Dict[str, Any]] entitycount = 0 for item in data: result.extend(item) # type: ignore entitycount = entitycount + 1 click.echo( helper.format_output( ctx, result, columns=ctx.columns if ctx.columns else const.COLUMNS_ENTITIES, ) ) if ctx.verbose: click.echo( 'History with {} rows from {} entities found.'.format( len(result), entitycount ) )
def health(ctx: Configuration): """Get system health from Home Assistant.""" info = api.get_health(ctx) ctx.echo( format_output( ctx, [info], columns=ctx.columns if ctx.columns else const.COLUMNS_DEFAULT, ) )
def core_update(ctx: Configuration): """Home Assistant core update.""" response = _handle_raw(ctx, 'core/info') data = response['data'] current_version = data['version'] latest_version = data['version_latest'] if StrictVersion(current_version) == StrictVersion(latest_version): ctx.echo("Already running the latest release") else: try: _handle(ctx, 'core/update', 'post') except (HomeAssistantCliError, HTTPError): pass
def supervisor_update(ctx: Configuration): """Home Assistant supervisor update.""" response = _handle_raw(ctx, 'supervisor/info') data = response['data'] current_version = int(data['version']) latest_version = int(data['version_latest']) if current_version == latest_version: ctx.echo("Already running the latest release") else: try: _handle(ctx, 'supervisor/update', 'post') except (HomeAssistantCliError, HTTPError): pass
def _init_ctx(ctx: Configuration) -> None: """Initialize ctx.""" # ctx is incomplete thus need to 'hack' around it # see bug https://github.com/pallets/click/issues/942 if not hasattr(ctx, 'server'): ctx.server = os.environ.get('HASS_SERVER', const.AUTO_SERVER) if not hasattr(ctx, 'token'): ctx.token = os.environ.get('HASS_TOKEN', None) if not hasattr(ctx, 'password'): ctx.password = os.environ.get('HASS_PASSWORD', None) if not hasattr(ctx, 'timeout'): ctx.timeout = int( os.environ.get('HASS_TIMEOUT', str(const.DEFAULT_TIMEOUT))) if not hasattr(ctx, 'insecure'): ctx.insecure = False if not hasattr(ctx, 'session'): ctx.session = None if not hasattr(ctx, 'cert'): ctx.cert = None if not hasattr(ctx, 'resolved_server'): ctx.resolved_server = resolve_server(ctx)
def _init_ctx(ctx: Configuration) -> None: """Initialize ctx.""" # ctx is incomplete thus need to 'hack' around it # see bug https://github.com/pallets/click/issues/942 if not hasattr(ctx, 'server'): ctx.server = os.environ.get('HASS_SERVER', const.AUTO_SERVER) if not hasattr(ctx, 'token'): ctx.token = os.environ.get('HASS_TOKEN', None) if not hasattr(ctx, 'password'): ctx.password = os.environ.get('HASS_PASSWORD', None) if not hasattr(ctx, 'timeout'): ctx.timeout = int( os.environ.get('HASS_TIMEOUT', str(const.DEFAULT_TIMEOUT)) ) if not hasattr(ctx, 'insecure'): ctx.insecure = False if not hasattr(ctx, 'session'): ctx.session = None if not hasattr(ctx, 'cert'): ctx.cert = None if not hasattr(ctx, 'resolved_server'): ctx.resolved_server = resolve_server(ctx)
def list_cmd(ctx: Configuration, servicefilter): """Get list of services.""" ctx.auto_output('table') services = api.get_services(ctx) result = [] # type: List[Dict[Any,Any]] if servicefilter == ".*": result = services else: result = services servicefilterre = reg.compile(servicefilter) # type: Pattern domains = [] for domain in services: domain_name = domain['domain'] domaindata = {} servicesdict = domain['services'] servicedata = {} for service in servicesdict: if servicefilterre.search( "{}.{}".format(domain_name, service) ): servicedata[service] = servicesdict[service] if servicedata: domaindata["services"] = servicedata domaindata["domain"] = domain_name domains.append(domaindata) result = domains flattenresult = [] # type: List[Dict[str,Any]] for domain in result: for service in domain['services']: item = {} item['domain'] = domain['domain'] item['service'] = service item = {**item, **domain['services'][service]} flattenresult.append(item) cols = [ ('DOMAIN', 'domain'), ('SERVICE', 'service'), ('DESCRIPTION', 'description'), ] ctx.echo( format_output( ctx, flattenresult, columns=ctx.columns if ctx.columns else cols ) )
def get(ctx: Configuration, entity): """Get/read entity state from Home Assistant.""" ctx.auto_output("table") state = api.get_state(ctx, entity) if state: ctx.echo( helper.format_output( ctx, [state], columns=ctx.columns if ctx.columns else const.COLUMNS_ENTITIES, ) ) else: _LOGGING.error("Entity with id: '%s' not found.", entity)
def cli(ctx: Configuration): """Get basic info from Home Assistant.""" ctx.auto_output("table") cols = [ ("BASE_URL", "base_url"), ("LOCATION", "location_name"), ("REQUIRES_API_PASSWORD", "requires_api_password"), ("VERSION", "version"), ] ctx.echo( format_output( ctx, [api.get_info(ctx)], columns=ctx.columns if ctx.columns else cols, ))
def call(ctx: Configuration, service, arguments): """Call a service.""" ctx.auto_output('data') _LOGGING.debug("service call <start>") parts = service.split(".") if len(parts) != 2: _LOGGING.error("Service name not following <domain>.<service> format.") sys.exit(1) _LOGGING.debug("Convert arguments %s to dict", arguments) data = to_attributes(arguments) _LOGGING.debug("service call_service") result = api.call_service(ctx, parts[0], parts[1], data) _LOGGING.debug("Formatting ouput") ctx.echo(format_output(ctx, result))
def call(ctx: Configuration, service, arguments): """Call a service.""" ctx.auto_output('data') _LOGGING.debug("service call <start>") parts = service.split(".") if len(parts) != 2: _LOGGING.error("Service name not following <domain>.<service> format") sys.exit(1) _LOGGING.debug("Convert arguments %s to dict", arguments) data = to_attributes(arguments) _LOGGING.debug("service call_service") result = api.call_service(ctx, parts[0], parts[1], data) _LOGGING.debug("Formatting output") ctx.echo(format_output(ctx, result))
def test_apimethod_completion(default_services) -> None: """Test completion for raw API methods.""" cfg = Configuration() result = autocompletion.api_methods(cfg, ["raw", "get"], "/api/disc") assert len(result) == 1 resultdict = dict(result) assert "/api/discovery_info" in resultdict
def cli(ctx: Configuration, template, datafile, local: bool) -> None: """Render templates on server or locally. TEMPLATE - jinja2 template file DATAFILE - yaml file with variables to pass to rendering """ variables = {} # type: Dict[str, Any] if datafile: variables = ctx.yamlload(datafile) templatestr = template.read() _LOGGING.debug("Rendering: %s Variables: %s", templatestr, variables) if local: output = render(template.name, variables, True) else: output = api.render_template(ctx, templatestr, variables) ctx.echo(output)
def test_wsapimethod_completion(default_services) -> None: """Test completion for raw ws API methods.""" cfg = Configuration() result = autocompletion.wsapi_methods(cfg, ["raw", "get"], "config/device_registry/l") assert len(result) == 1 resultdict = dict(result) assert "config/device_registry/list" in resultdict
def websocket(ctx: Configuration, wstype, json): # noqa: D301 """Send a websocket request against /api/websocket. WSTYPE is name of websocket methods. \b --json is dictionary to pass in addition to the type. Example: --json='{ "area_id":"2c8bf93c8082492f99c989896962f207" }' """ if json: data = json_.loads(json) else: data = {} frame = {'type': wstype} frame = {**frame, **data} # merging data into frame response = cast(List[Dict[str, Any]], api.wsapi(ctx, frame)) ctx.echo(format_output(ctx, response))
def cli(ctx: Configuration, template, datafile, local: bool) -> None: """Render templates on server or locally. TEMPLATE - jinja2 template file DATAFILE - yaml file with variables to pass to rendering """ variables = {} # type: Dict[str, Any] if datafile: variables = yaml.load(datafile) templatestr = template.read() _LOGGING.debug("Rendering: %s Variables: %s", templatestr, variables) if local: output = render(template.name, variables, True) else: output = api.render_template(ctx, templatestr, variables) ctx.echo(output)
def listcmd(ctx: Configuration, areafilter: str): """List all areas from Home Assistant.""" ctx.auto_output("table") areas = api.get_areas(ctx) result = [] # type: List[Dict] if areafilter == ".*": result = areas else: areafilterre = re.compile(areafilter) # type: Pattern for device in areas: if areafilterre.search(device['name']): result.append(device) cols = [('ID', 'area_id'), ('NAME', 'name')] ctx.echo( helper.format_output(ctx, result, columns=ctx.columns if ctx.columns else cols))
def assign( ctx: Configuration, area_id_or_name, names: List[str], match: Optional[str] = None, ): """Update area on one or more devices. NAMES - one or more name or id (Optional) """ ctx.auto_output("data") devices = api.get_devices(ctx) result = [] # type: List[Dict] area = api.find_area(ctx, area_id_or_name) if not area: _LOGGING.error("Could not find area with id or name: %s", area_id_or_name) sys.exit(1) if match: if match == ".*": result = devices else: devicefilterre = re.compile(match) # type: Pattern for device in devices: if devicefilterre.search(device['name']): result.append(device) for id_or_name in names: device = next( (x for x in devices if x['id'] == id_or_name), None # type: ignore ) if not device: device = next( (x for x in devices if x['name'] == id_or_name), None, # type: ignore ) if not device: _LOGGING.error("Could not find device with id or name: %s", id_or_name) sys.exit(1) result.append(device) for device in result: output = api.assign_area(ctx, device['id'], area['area_id']) if output['success']: ctx.echo("Successfully assigned '{}' to '{}'".format( area['name'], device['name'])) else: _LOGGING.error("Failed to assign '%s' to '%s'", area['name'], device['name']) ctx.echo(str(output))
def fire(ctx: Configuration, event, json): """Fire event in Home Assistant.""" if json: click.echo("Fire {}".format(event)) response = api.fire_event(ctx, event, json) else: existing = raw_format_output(ctx.output, [{}], ctx.yaml()) new = click.edit(existing, extension='.{}'.format(ctx.output)) if new: click.echo("Fire {}".format(event)) if ctx.output == 'yaml': data = ctx.yamlload(new) else: data = json_.loads(new) response = api.fire_event(ctx, event, data) else: click.echo("No edits/changes.") return if response: ctx.echo(raw_format_output(ctx.output, [response], ctx.yaml()))
def listcmd(ctx: Configuration, areafilter: str): """List all areas from Home Assistant.""" ctx.auto_output("table") areas = api.get_areas(ctx) result = [] # type: List[Dict] if areafilter == ".*": result = areas else: areafilterre = re.compile(areafilter) # type: Pattern for device in areas: if areafilterre.search(device['name']): result.append(device) cols = [('ID', 'area_id'), ('NAME', 'name')] ctx.echo( helper.format_output( ctx, result, columns=ctx.columns if ctx.columns else cols ) )
def fire(ctx: Configuration, event, json): """Fire event in Home Assistant.""" if json: click.echo("Fire {}".format(event)) response = api.fire_event(ctx, event, json) else: existing = raw_format_output(ctx.output, {}) # type: ignore new = click.edit(existing, extension='.{}'.format(ctx.output)) if new: click.echo("Fire {}".format(event)) if ctx.output == 'yaml': data = yaml.load(new) else: data = json_.loads(new) response = api.fire_event(ctx, event, data) else: click.echo("No edits/changes.") return if response: ctx.echo(raw_format_output(ctx.output, response)) # type: ignore
def delete(ctx: Configuration, entity): """Delete entity state from Home Assistant.""" ctx.auto_output("table") deleted = api.remove_state(ctx, entity) if deleted: ctx.echo("State for entity %s deleted.", entity) else: ctx.echo("Entity %s not found.", entity)
def format_output( ctx: Configuration, data: List[Dict[str, Any]], columns: Optional[List] = None, ) -> str: """Format data to output based on settings in ctx/Context.""" return raw_format_output( ctx.output, data, ctx.yaml(), columns, ctx.no_headers, ctx.table_format, ctx.sort_by, )
def restapi(ctx: Configuration, method: str, path: str, data: Optional[Dict] = None) -> requests.Response: """Make a call to the Home Assistant REST API.""" if data is None: data_str = None else: data_str = json.dumps(data, cls=JSONEncoder) if not ctx.session: ctx.session = requests.Session() ctx.session.verify = not ctx.insecure if ctx.cert: ctx.session.cert = ctx.cert _LOGGER.debug( "Session: verify(%s), cert(%s)", ctx.session.verify, ctx.session.cert, ) headers = {CONTENT_TYPE: hass.CONTENT_TYPE_JSON} # type: Dict[str, Any] if ctx.token: headers["Authorization"] = "Bearer {}".format(ctx.token) if ctx.password: headers["x-ha-access"] = ctx.password url = urllib.parse.urljoin(resolve_server(ctx) + path, "") try: if method == METH_GET: return requests.get(url, params=data_str, headers=headers) return requests.request(method, url, data=data_str, headers=headers) except requests.exceptions.ConnectionError: raise HomeAssistantCliError("Error connecting to {}".format(url)) except requests.exceptions.Timeout: error = "Timeout when talking to {}".format(url) _LOGGER.exception(error) raise HomeAssistantCliError(error)
def test_service_completion(default_services) -> None: """Test completion for services with filter.""" with requests_mock.Mocker() as mock: mock.get( 'http://localhost:8123/api/services', json=default_services, status_code=200, ) cfg = Configuration() result = autocompletion.services(cfg, ["service", "call"], "light.turn") assert len(result) == 2 resultdict = dict(result) assert "light.turn_on" in resultdict assert "light.turn_off" in resultdict
def restapi( ctx: Configuration, method: str, path: str, data: Optional[Dict] = None ) -> requests.Response: """Make a call to the Home Assistant REST API.""" if data is None: data_str = None else: data_str = json.dumps(data, cls=JSONEncoder) if not ctx.session: ctx.session = requests.Session() ctx.session.verify = not ctx.insecure if ctx.cert: ctx.session.cert = ctx.cert _LOGGER.debug( "Session: verify(%s), cert(%s)", ctx.session.verify, ctx.session.cert, ) headers = {CONTENT_TYPE: hass.CONTENT_TYPE_JSON} # type: Dict[str, Any] if ctx.token: headers["Authorization"] = "Bearer {}".format(ctx.token) if ctx.password: headers["x-ha-access"] = ctx.password url = urllib.parse.urljoin(resolve_server(ctx) + path, "") try: if method == METH_GET: return requests.get(url, params=data_str, headers=headers) return requests.request(method, url, data=data_str, headers=headers) except requests.exceptions.ConnectionError: raise HomeAssistantCliError("Error connecting to {}".format(url)) except requests.exceptions.Timeout: error = "Timeout when talking to {}".format(url) _LOGGER.exception(error) raise HomeAssistantCliError(error)
def cli(ctx: Configuration, service: str, entity: str) -> None: """Show the location of the config or an entity on a map.""" latitude = None longitude = None if entity: thing = entity data = api.get_state(ctx, entity) if data: attr = data.get('attributes', {}) latitude = attr.get('latitude') longitude = attr.get('longitude') thing = attr.get('friendly_name', entity) else: thing = "configuration" response = api.get_config(ctx) if response: latitude = response.get('latitude') longitude = response.get('longitude') thing = response.get('location_name', thing) if latitude and longitude: urlpattern = SERVICE.get(service) import urllib.parse if urlpattern: url = urlpattern.format(latitude, longitude, urllib.parse.quote_plus(thing)) ctx.echo("{} location is at {}, {}".format(thing, latitude, longitude)) webbrowser.open_new_tab(url) else: ctx.echo( "Could not find url pattern for service {}".format(service)) else: ctx.echo("No exact location info found in {}".format(thing)) sys.exit(2)
def edit(ctx: Configuration, entity, newstate, attributes, merge, json): """Edit entity state from Home Assistant.""" ctx.auto_output('data') new_state = newstate if json: _LOGGING.debug( "JSON found overriding/creating new state for entity %s", entity) wanted_state = json_.loads(json) elif new_state or attributes: wanted_state = {} existing_state = api.get_state(ctx, entity) if existing_state: ctx.echo("Existing state found for %s", entity) if merge: wanted_state = existing_state else: ctx.echo("No existing state found for '%s'", entity) if attributes: attributes_dict = helper.to_attributes(attributes) new_attr = wanted_state.get('attributes', {}) new_attr.update(attributes_dict) # This is not honoring merge! wanted_state['attributes'] = new_attr if newstate: wanted_state['state'] = newstate else: if not existing_state: raise ValueError("No new or existing state provided.") wanted_state['state'] = existing_state['state'] else: existing = api.get_state(ctx, entity) if existing: existing_raw = helper.raw_format_output(ctx.output, existing, ctx.yaml()) else: existing_raw = helper.raw_format_output(ctx.output, {}, ctx.yaml()) new = click.edit(existing_raw, extension='.{}'.format(ctx.output)) if new is not None: ctx.echo("Updating '%s'", entity) if ctx.output == 'yaml': wanted_state = ctx.yamlload(new) if ctx.output == 'json': wanted_state = json_.loads(new) api.set_state(ctx, entity, wanted_state) else: ctx.echo("No edits/changes returned from editor.") return _LOGGING.debug("wanted: %s", str(wanted_state)) result = api.set_state(ctx, entity, wanted_state) ctx.echo("Entity %s updated successfully", entity) _LOGGING.debug("Updated to: %s", result)
def edit(ctx: Configuration, entity, newstate, attributes, merge, json): """Edit entity state from Home Assistant.""" ctx.auto_output('data') if json: _LOGGING.debug( "json found overriding/creating new state for entity %s", entity ) wanted_state = json_.loads(json) elif newstate or attributes: wanted_state = {} existing_state = api.get_state(ctx, entity) if existing_state: ctx.echo("Existing state found for %s", entity) if merge: wanted_state = existing_state else: ctx.echo("No existing state found for '%s'", entity) if attributes: attributes_dict = helper.to_attributes(attributes) newattr = wanted_state.get('attributes', {}) newattr.update(attributes_dict) # this is not hornoring merge! wanted_state['attributes'] = newattr if newstate: wanted_state['state'] = newstate else: if not existing_state: raise ValueError("No new or existing state provided.") wanted_state['state'] = existing_state['state'] else: existing = api.get_state(ctx, entity) if existing: existingraw = helper.raw_format_output( ctx.output, [existing], ctx.yaml() )[0] else: existingraw = helper.raw_format_output( ctx.output, [{}], ctx.yaml() )[0] new = click.edit(existingraw, extension='.{}'.format(ctx.output)) if new is not None: ctx.echo("Updating '%s'", entity) if ctx.output == 'yaml': wanted_state = ctx.yamlload(new) if ctx.output == 'json': wanted_state = json_.loads(new) api.set_state(ctx, entity, wanted_state) else: ctx.echo("No edits/changes returned from editor.") return _LOGGING.debug("wanted: %s", str(wanted_state)) result = api.set_state(ctx, entity, wanted_state) ctx.echo("Entity %s updated succesfully", entity) _LOGGING.debug("Updated to: %s", result)
def off_cmd(ctx: Configuration, entities): """Turn entity off.""" ctx.auto_output("table") _homeassistant_cmd(ctx, entities, 'turn_off', "turned off")
def cli(ctx: Configuration): """Call the raw API (advanced).""" ctx.auto_output("data")
def on_cmd(ctx: Configuration, entities): """Turn entity on.""" ctx.auto_output("table") _homeassistant_cmd(ctx, entities, 'turn_on', "turned on")
def cli( ctx: Configuration, verbose: bool, server: str, token: Optional[str], password: Optional[str], output: str, timeout: int, debug: bool, insecure: bool, showexceptions: bool, cert: str, columns: str, no_headers: bool, table_format: str, sort_by: Optional[str], ) -> None: """Command line interface for Home Assistant.""" ctx.verbose = verbose ctx.server = server ctx.token = token ctx.password = password ctx.timeout = timeout ctx.output = output ctx.debug = debug ctx.insecure = insecure ctx.showexceptions = showexceptions ctx.cert = cert ctx.columns = to_tuples(columns) ctx.no_headers = no_headers ctx.table_format = table_format ctx.sort_by = sort_by # type: ignore _LOGGER.debug("Using settings: %s", ctx) if debug: debug_requests_on()
def assign( ctx: Configuration, area_id_or_name, names: List[str], match: Optional[str] = None, ): """Update area on one or more devices. NAMES - one or more name or id (Optional) """ ctx.auto_output("data") devices = api.get_devices(ctx) result = [] # type: List[Dict] area = api.find_area(ctx, area_id_or_name) if not area: _LOGGING.error( "Could not find area with id or name: %s", area_id_or_name ) sys.exit(1) if match: if match == ".*": result = devices else: devicefilterre = re.compile(match) # type: Pattern for device in devices: if devicefilterre.search(device['name']): result.append(device) for id_or_name in names: device = next( # type: ignore (x for x in devices if x['id'] == id_or_name), None ) if not device: device = next( # type: ignore (x for x in devices if x['name'] == id_or_name), None ) if not device: _LOGGING.error( "Could not find device with id or name: %s", id_or_name ) sys.exit(1) result.append(device) for device in result: output = api.assign_area(ctx, device['id'], area['area_id']) if output['success']: ctx.echo( "Successfully assigned '{}' to '{}'".format( area['name'], device['name'] ) ) else: _LOGGING.error( "Failed to assign '%s' to '%s'", area['name'], device['name'] ) ctx.echo(str(output))
def toggle(ctx: Configuration, entities): """Toggle state for one or more entities in Home Assistant.""" ctx.auto_output("table") _homeassistant_cmd(ctx, entities, 'toggle', "toggled")