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 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 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 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 _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 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 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 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 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 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 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 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 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 = 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 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 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 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 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 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)