コード例 #1
0
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
        )
    )
コード例 #2
0
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
        )
    )
コード例 #3
0
ファイル: entity.py プロジェクト: walnerz/home-assistant-cli
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))
コード例 #4
0
ファイル: entity.py プロジェクト: bbrendon/home-assistant-cli
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)
コード例 #5
0
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)
コード例 #6
0
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,
        ))
コード例 #7
0
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)
コード例 #8
0
ファイル: entity.py プロジェクト: bbrendon/home-assistant-cli
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
            )
        )
コード例 #9
0
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
            )
        )
コード例 #10
0
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,
        )
    )
コード例 #11
0
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
コード例 #12
0
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
コード例 #13
0
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)
コード例 #14
0
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)
コード例 #15
0
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
        )
    )
コード例 #16
0
ファイル: service.py プロジェクト: todun/home-assistant-cli
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
        )
    )
コード例 #17
0
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)
コード例 #18
0
ファイル: info.py プロジェクト: walnerz/home-assistant-cli
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,
        ))
コード例 #19
0
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))
コード例 #20
0
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))
コード例 #21
0
ファイル: test_raw.py プロジェクト: todun/home-assistant-cli
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
コード例 #22
0
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)
コード例 #23
0
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
コード例 #24
0
ファイル: raw.py プロジェクト: sebastienvg/home-assistant-cli
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))
コード例 #25
0
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)
コード例 #26
0
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))
コード例 #27
0
ファイル: device.py プロジェクト: walnerz/home-assistant-cli
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))
コード例 #28
0
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()))
コード例 #29
0
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
        )
    )
コード例 #30
0
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
コード例 #31
0
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)
コード例 #32
0
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)
コード例 #33
0
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,
    )
コード例 #34
0
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)
コード例 #35
0
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
コード例 #36
0
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)
コード例 #37
0
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)
コード例 #38
0
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)
コード例 #39
0
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)
コード例 #40
0
def off_cmd(ctx: Configuration, entities):
    """Turn entity off."""
    ctx.auto_output("table")
    _homeassistant_cmd(ctx, entities, 'turn_off', "turned off")
コード例 #41
0
def cli(ctx: Configuration):
    """Call the raw API (advanced)."""
    ctx.auto_output("data")
コード例 #42
0
def off_cmd(ctx: Configuration, entities):
    """Turn entity off."""
    ctx.auto_output("table")
    _homeassistant_cmd(ctx, entities, 'turn_off', "turned off")
コード例 #43
0
def on_cmd(ctx: Configuration, entities):
    """Turn entity on."""
    ctx.auto_output("table")
    _homeassistant_cmd(ctx, entities, 'turn_on', "turned on")
コード例 #44
0
ファイル: raw.py プロジェクト: sebastienvg/home-assistant-cli
def cli(ctx: Configuration):
    """Call the raw API (advanced)."""
    ctx.auto_output("data")
コード例 #45
0
def on_cmd(ctx: Configuration, entities):
    """Turn entity on."""
    ctx.auto_output("table")
    _homeassistant_cmd(ctx, entities, 'turn_on', "turned on")
コード例 #46
0
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()
コード例 #47
0
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))
コード例 #48
0
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()
コード例 #49
0
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")
コード例 #50
0
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")