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 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, 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 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 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 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 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 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 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 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 on_cmd(ctx: Configuration, entities): """Turn entity on.""" ctx.auto_output("table") _homeassistant_cmd(ctx, entities, 'turn_on', "turned on")
def hardware(ctx: Configuration): """Home Assistant hardware info.""" ctx.auto_output('data')
def cli(ctx: Configuration): """Home Assistant (former Hass.io) commands.""" ctx.auto_output("data")
def core(ctx: Configuration): """Home Assistant core commands.""" ctx.auto_output('data')
def addons(ctx: Configuration): """Home Assistant addons commands.""" ctx.auto_output('data')
def multicast(ctx: Configuration): """Home Assistant Multicast commands.""" ctx.auto_output('data')
def dns(ctx: Configuration): """Home Assistant DNS commands.""" ctx.auto_output('data')
def cli(ctx: Configuration): """Call the raw API (advanced).""" ctx.auto_output("data")
def cli(ctx: Configuration): """Call the raw API (advanced).""" ctx.auto_output("data")
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")
def off_cmd(ctx: Configuration, entities): """Turn entity off.""" ctx.auto_output("table") _homeassistant_cmd(ctx, entities, 'turn_off', "turned off")
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 supervisor(ctx: Configuration): """Home Assistant supervisor commands.""" 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 host(ctx: Configuration): """Home Assistant host commands.""" ctx.auto_output('data')
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")
def ha_cli(ctx: Configuration): """Home Assistant ha-cli commands.""" ctx.auto_output('data')
def off_cmd(ctx: Configuration, entities): """Turn entity off.""" ctx.auto_output("table") _homeassistant_cmd(ctx, entities, 'turn_off', "turned off")
def snapshot(ctx: Configuration): """Home Assistant snapshot commands.""" ctx.auto_output('data')