Example #1
0
def stack_options(func):
    """
    stack_options is a decorator which adds the stack and environment arguments
    to the click function ``func``.

    :param func: The click function to add the arguments to.
    :type func: function
    :returns: function
    """
    func = click.argument("stack")(func)
    func = click.argument("environment")(func)
    return func
Example #2
0
def change_set_options(func):
    """
    change_set_options is a decorator which adds the environment, stack and
    change set name arguments to the click function ``func``.

    :param func: The click function to add the arguments to.
    :type func: function
    :returns: function
    """
    func = click.argument("change_set_name")(func)
    func = click.argument("stack")(func)
    func = click.argument("environment")(func)
    return func
Example #3
0
def clone_target_arg():
    """Represent target to clone/branch."""
    return click.argument(
        "target",
        metavar="TARGET",
        type=click.STRING,
    )
Example #4
0
def task_option(__fun: Callable) -> Callable:
    """Add task selection options.

    Note:
        This is only here to reduce duplication in command setup.

    Args:
        __fun: Function to add options to

    Returns:
        Function with additional options

    """
    __fun = click.option(
        '-x',
        '--from-dir',
        is_flag=True,
        expose_value=False,
        is_eager=True,
        callback=task_from_dir,
        help='Use directory name as task name.'
    )(__fun)
    __fun = click.argument(
        'task',
        default='default',
        envvar='RDIAL_TASK',
        required=False,
        type=TaskNameParamType()
    )(__fun)
    return __fun
Example #5
0
def decorate_plotting_command(func):
    """A decorator to make a plotting command."""
    func = DatasetQuery.decorate(func)
    func = CeleryProgressGroup.decorate(func)
    func = click.argument("component", type=str)(func)
    func = click.option("--force/--no-force", default=False, help="Force update plots.")(func)
    return func
Example #6
0
 def database_connection_arg(fn):
     arg = click.argument(
         "database-connection",
         type=DatabaseConnectionParam(exists=True),
         doc_help=(
             "A connection URI for a database, or a path on the file system"))
     return arg(fn)
Example #7
0
    def custom_scores_argument(func):
        def callback(ctx, param, value):
            min_a = min_arg or 1
            mutli = 1
            error = ''
            if ('evaluation' in ctx.meta and ctx.meta['evaluation']) or force_eval:
                mutli += 1
                error += '- %d evaluation file(s) \n' % min_a
            if 'train' in ctx.meta and ctx.meta['train']:
                mutli += 1
                error += '- %d training file(s) \n' % min_a
            # add more test here if other inputs are needed

            min_a *= mutli
            ctx.meta['min_arg'] = min_a
            if len(value) < 1 or len(value) % ctx.meta['min_arg'] != 0:
                raise click.BadParameter(
                    'The number of provided scores must be > 0 and a multiple of %d '
                    'because the following files are required:\n'
                    '- %d development file(s)\n' % (min_a, min_arg or 1) +
                    error, ctx=ctx
                )
            ctx.meta['scores'] = value
            return value
        return click.argument(
            'scores', type=click.Path(exists=True),
            callback=callback, **kwargs
        )(func)
Example #8
0
def optional_tools_arg(multiple=False, allow_uris=False):
    """ Decorate click method as optionally taking in the path to a tool
    or directory of tools. If no such argument is given the current working
    directory will be treated as a directory of tools.
    """
    arg_type_class = click.Path if not allow_uris else UriLike
    arg_type = arg_type_class(
        exists=True,
        file_okay=True,
        dir_okay=True,
        readable=True,
        resolve_path=True,
    )
    if allow_uris:
        name = "uris" if multiple else "uri"
    else:
        name = "paths" if multiple else "path"
    nargs = -1 if multiple else 1
    return click.argument(
        name,
        metavar="TOOL_PATH",
        type=arg_type,
        nargs=nargs,
        callback=_optional_tools_default,
    )
Example #9
0
def sample_path(fn):
    arg = click.argument(
        "sample-path",
        type=click.Path(exists=True, dir_okay=False, file_okay=True),
        doc_help=(
            "The path to the deconvoluted sample file"))
    return arg(fn)
Example #10
0
File: cli.py Project: 20c/ngage
def connect_options(f):
    f = click.argument('host', nargs=1)(f)
    f = click.option('--port', help='port to connect to, default per platform')(f)
    f = click.option('--type', help='type of connection')(f)
    f = click.option('--user', help='username', envvar='NGAGE_USER')(f)
    f = click.option('--password', help='password to use if not using key auth')(f)
    return f
Example #11
0
def post_options():
    """Standard arguments and options for posting timeseries readings.
    """
    options = [
        click.argument('port'),
        click.argument('value', type=JSONParamType()),
        click.option('--timestamp', metavar='DATE',
                     help='the time of the reading'),
    ]

    def wrapper(func):
        func.__doc__ += _post_options_docs
        for option in reversed(options):
            func = option(func)
        return func
    return wrapper
def db_string_option(f):
    def callback(ctx, param, value):
        db = ctx.ensure_object(Database)
        db.setup(value)
        return value
    return click.argument('db_string', expose_value=False,
                          envvar="ROLLUP_DB_STRING",
                          callback=callback)(f)
Example #13
0
 def decorate(f, **kwargs):
     """
     Work of actually decorating a function -- wrapped in here because we
     want to dispatch depending on how this is invoked
     """
     metavar = kwargs.get("metavar", "ENDPOINT_ID")
     f = click.argument("endpoint_id", metavar=metavar, type=click.UUID)(f)
     return f
 def specify_id_attrs(f):
     try:
         ids = res.identity_attributes.keys()
     except AttributeError:
         ids = res.identity_attributes
     for id in reversed(ids):
         f = click.argument(id, required=True)(f)
     return f
Example #15
0
def argument(*args, **kwargs):
    """Make Click arguments Cloudify specific

    This exists purely for aesthetic reasons, otherwise
    Some decorators are called `@click.something` instead of
    `@cfy.something`
    """
    return click.argument(*args, **kwargs)
Example #16
0
 def wrap(func):
     decorators = [
         click.option('--parent-type', default=parent_type_default,
                      show_default=True, cls=parent_type_cls,
                      help='type of Girder parent target', type=click.Choice(parent_types)),
         click.argument('parent_id'),
         click.argument(
             'local_folder',
             type=click.Path(exists=path_exists, dir_okay=True,
                             writable=path_writable, readable=True),
             default=path_default,
             nargs=1 if not multiple_local else -1,
             required=multiple_local
         ),
     ]
     for decorator in reversed(decorators):
         func = decorator(func)
     return func
Example #17
0
def domain_argument(f):
    def callback(ctx, param, value):
        state = ctx.ensure_object(State)
        # if no dot in the domain name, assume we should add zone
        if value.find('.') == -1:
            value = '%s.%s' % (value, state.ZONE)
        state.DOMAIN = value
        return value
    return click.argument('DOMAIN', expose_value=False, callback=callback)(f)
Example #18
0
def required_workflow_arg():
    arg_type = click.Path(
        exists=True,
        file_okay=True,
        dir_okay=False,
        readable=True,
        resolve_path=False,
    )
    return click.argument("workflow_path", metavar="WORKFLOW_PATH", type=arg_type)
Example #19
0
def required_tool_arg():
    """ Decorate click method as requiring the path to a single tool.
    """
    arg_type = click.Path(
        exists=True,
        file_okay=True,
        dir_okay=False,
        readable=True,
        resolve_path=True,
    )
    return click.argument('path', metavar="TOOL_PATH", type=arg_type)
Example #20
0
def optional_tools_or_packages_arg(multiple=False):
    """ Decorate click method as optionally taking in the path to a tool
    or directory of tools or a Conda package. If no such argument is given
    the current working directory will be treated as a directory of tools.
    """
    name = "paths" if multiple else "path"
    nargs = -1 if multiple else 1
    return click.argument(
        name,
        metavar="TARGET",
        nargs=nargs,
    )
Example #21
0
def tool_test_json():
    target_path = click.Path(
        file_okay=True,
        dir_okay=False,
        resolve_path=True,
    )
    return click.argument(
        'path',
        metavar="FILE_PATH",
        type=target_path,
        default="tool_test_output.json",
    )
Example #22
0
def value_param(f):
    def validate(ctx, param, value):
        try:
            value = yaml.safe_load(value)
        except (yaml.scanner.ScannerError, yaml.parser.ParserError) as e:
            msg = 'The value is not valid YAML.\n\n{}\n{}'.format(
                e.problem, e.problem_mark)
            raise click.BadParameter(msg)
        return value

    decorator = click.argument('value', callback=validate)
    return decorator(f)
Example #23
0
def get_click_client(app: App) -> Callable:
    @click.group(invoke_without_command=True, help='API Star')
    @click.option('--version', is_flag=True, help='Display the `apistar` version number.')
    @click.pass_context
    def client(ctx: click.Context, version: bool) -> None:
        if ctx.invoked_subcommand is not None:
            return

        if version:
            from apistar import __version__
            click.echo(__version__)
        else:
            click.echo(ctx.get_help())

    for command in app.commands:

        command_signature = inspect.signature(command)
        for param in reversed(list(command_signature.parameters.values())):
            name = param.name.replace('_', '-')
            annotation = param.annotation
            kwargs = {}
            if hasattr(annotation, 'default'):
                kwargs['default'] = annotation.default
            if hasattr(annotation, 'description'):
                kwargs['help'] = annotation.description

            if issubclass(annotation, (bool, schema.Boolean)):
                kwargs['is_flag'] = True
                kwargs['default'] = False
            elif hasattr(annotation, 'choices'):
                kwargs['type'] = click.Choice(annotation.choices)
            elif hasattr(annotation, 'native_type'):
                kwargs['type'] = annotation.native_type
            elif annotation is inspect.Signature.empty:
                kwargs['type'] = str
            else:
                kwargs['type'] = annotation

            if 'default' in kwargs:
                name = '--%s' % param.name.replace('_', '-')
                option = click.option(name, **kwargs)
                command = option(command)
            else:
                kwargs.pop('help', None)
                argument = click.argument(param.name, **kwargs)
                command = argument(command)

        cmd_wrapper = click.command(help=command.__doc__)
        command = cmd_wrapper(command)

        client.add_command(command)

    return client
Example #24
0
def signature_analysis(cmd):
    cmd = click.option('--model', '-m', default=None, type=click.Path(exists=True, dir_okay=False),
                       help='Path to model file.')(cmd)
    cmd = click.option('--parameter', '-p',
                       default=None,
                       type=click.Path(exists=True, dir_okay=False),
                       help='(optional) Path to parameter file.'
                       )(cmd)
    cmd = click.argument("scheme",
                         type=click.Path(exists=True, dir_okay=False),
                         required=False
                         )(cmd)
    return cmd
Example #25
0
 def auto_create_params(self):
     argspec = inspect.getargspec(self.real_func)
     args = argspec.args
     if args[0] == "self":
         del args[0]
     if self.pass_script_info and args[0] == "info":
         del args[0]
     num_mandatory_args = len(args) - len(argspec.defaults) if argspec.defaults else len(args)
     if num_mandatory_args:
         mandatory_args = args[:num_mandatory_args]
         mandatory_args.reverse()
         for arg in mandatory_args:
             if not self.has_param(arg):
                 click.argument(arg)(self.unbound_func)
     if len(args) > num_mandatory_args:
         for i, arg in enumerate(args[num_mandatory_args:]):
             if not self.has_param(arg):
                 optname = "--%s" % arg.replace("_", "-")
                 default = argspec.defaults[i]
                 if isinstance(default, bool):
                     optname += "/--no-%s" % arg.replace("_", "-")
                 click.option(optname, default=default)(self.unbound_func)
Example #26
0
def optional_project_arg(exists=True):
    arg_type = click.Path(
        exists=exists,
        file_okay=False,
        dir_okay=True,
        writable=True,
        resolve_path=True,
    )
    return click.argument(
        'path',
        metavar="PROJECT",
        default=".",
        type=arg_type
    )
Example #27
0
def text_arg(__func: Callable) -> Callable:
    """Add task selection click commands.

    Note:
        This is only here to reduce duplication in command setup.

    Args:
        __func: Function to add options to

    Returns:
        Function with additional options

    """
    return argument('text')(__func)
Example #28
0
    def _arg_date(f):
        def callback(ctx, param, value):
            try:
                value = dt.strptime(value, ctx.params[date_frmt_key])
            except KeyError:
                raise click.ClickException("Need to use `date_format_opt` when using `date_arg`")
            except ValueError:
                raise click.BadParameter(
                    "Cannot parse {v} to date with format {f}".format(v=value, f=ctx.params["date_frmt"])
                )
            else:
                return value

        return click.argument(var, metavar=metavar, callback=callback)(f)
Example #29
0
def arg_job_number(f):
    def callback(ctx, param, value):
        try:
            value = int(value)
        except:
            raise click.BadParameter("Must specify an integer >= 0")

        if value < 0:
            raise click.BadParameter("Must specify an integer >= 0")
        elif value == 0:
            return value
        else:
            return value - 1

    return click.argument("job_number", nargs=1, callback=callback, metavar="<job_number>")(f)
Example #30
0
def recipe_arg(multiple=True):
    name = "paths" if multiple else "path"
    nargs = -1 if multiple else 1
    return click.argument(
        name,
        metavar="RECIPE_DIR",
        type=click.Path(
            exists=True,
            file_okay=True,
            dir_okay=True,
            resolve_path=True,
        ),
        nargs=nargs,
        callback=_optional_tools_default,
    )
Example #31
0
class DreameVacuum(MiotDevice, VacuumInterface):
    _mappings = MIOT_MAPPING

    @command(default_output=format_output(
        "\n",
        "Battery level: {result.battery_level}\n"
        "Brush life level: {result.brush_life_level}\n"
        "Brush left time: {result.brush_left_time}\n"
        "Charging state: {result.charging_state}\n"
        "Cleaning mode: {result.cleaning_mode}\n"
        "Device fault: {result.device_fault}\n"
        "Device status: {result.device_status}\n"
        "Filter left level: {result.filter_left_time}\n"
        "Filter life level: {result.filter_life_level}\n"
        "Life brush main: {result.life_brush_main}\n"
        "Life brush side: {result.life_brush_side}\n"
        "Life sieve: {result.life_sieve}\n"
        "Map view: {result.map_view}\n"
        "Operating mode: {result.operating_mode}\n"
        "Side cleaning brush left time: {result.brush_left_time2}\n"
        "Side cleaning brush life level: {result.brush_life_level2}\n"
        "Time zone: {result.timezone}\n"
        "Timer enabled: {result.timer_enable}\n"
        "Timer start time: {result.start_time}\n"
        "Timer stop time: {result.stop_time}\n"
        "Voice package: {result.voice_package}\n"
        "Volume: {result.volume}\n"
        "Water flow: {result.water_flow}\n"
        "Water box attached: {result.is_water_box_carriage_attached} \n"
        "Cleaning time: {result.cleaning_time}\n"
        "Cleaning area: {result.cleaning_area}\n"
        "First clean time: {result.first_clean_time}\n"
        "Total clean time: {result.total_clean_time}\n"
        "Total clean times: {result.total_clean_times}\n"
        "Total clean area: {result.total_clean_area}\n",
    ))
    def status(self) -> DreameVacuumStatus:
        """State of the vacuum."""

        return DreameVacuumStatus(
            {
                prop["did"]: prop["value"] if prop["code"] == 0 else None
                for prop in self.get_properties_for_mapping(max_properties=10)
            },
            self.model,
        )

    # TODO: check the actual limit for this
    MANUAL_ROTATION_MAX = 120
    MANUAL_ROTATION_MIN = -MANUAL_ROTATION_MAX
    MANUAL_DISTANCE_MAX = 300
    MANUAL_DISTANCE_MIN = -300

    @command()
    def start(self) -> None:
        """Start cleaning."""
        return self.call_action("start_clean")

    @command()
    def stop(self) -> None:
        """Stop cleaning."""
        return self.call_action("stop_clean")

    @command()
    def home(self) -> None:
        """Return to home."""
        return self.call_action("home")

    @command()
    def identify(self) -> None:
        """Locate the device (i am here)."""
        return self.call_action("locate")

    @command()
    def reset_mainbrush_life(self) -> None:
        """Reset main brush life."""
        return self.call_action("reset_mainbrush_life")

    @command()
    def reset_filter_life(self) -> None:
        """Reset filter life."""
        return self.call_action("reset_filter_life")

    @command()
    def reset_sidebrush_life(self) -> None:
        """Reset side brush life."""
        return self.call_action("reset_sidebrush_life")

    @command()
    def play_sound(self) -> None:
        """Play sound."""
        return self.call_action("play_sound")

    @command()
    def fan_speed(self):
        """Return fan speed."""
        dreame_vacuum_status = self.status()
        fanspeed = dreame_vacuum_status.cleaning_mode
        if not fanspeed or fanspeed.value == -1:
            _LOGGER.warning("Unknown fanspeed value received")
            return
        return {fanspeed.name: fanspeed.value}

    @command(click.argument("speed", type=int))
    def set_fan_speed(self, speed: int):
        """Set fan speed.

        :param int speed: Fan speed to set
        """
        fanspeeds_enum = _get_cleaning_mode_enum_class(self.model)
        fanspeed = None
        if not fanspeeds_enum:
            return
        try:
            fanspeed = fanspeeds_enum(speed)
        except ValueError:
            _LOGGER.error(f"Unknown fanspeed value passed {speed}")
            return None
        click.echo(f"Setting fanspeed to {fanspeed.name}")
        return self.set_property("cleaning_mode", fanspeed.value)

    @command()
    def fan_speed_presets(self) -> FanspeedPresets:
        """Return available fan speed presets."""
        fanspeeds_enum = _get_cleaning_mode_enum_class(self.model)
        if not fanspeeds_enum:
            return {}
        return _enum_as_dict(fanspeeds_enum)

    @command(click.argument("speed", type=int))
    def set_fan_speed_preset(self, speed_preset: int) -> None:
        """Set fan speed preset speed."""
        if speed_preset not in self.fan_speed_presets().values():
            raise ValueError(
                f"Invalid preset speed {speed_preset}, not in: {self.fan_speed_presets().values()}"
            )
        self.set_fan_speed(speed_preset)

    @command()
    def waterflow(self):
        """Get water flow setting."""
        dreame_vacuum_status = self.status()
        waterflow = dreame_vacuum_status.water_flow
        if not waterflow or waterflow.value == -1:
            _LOGGER.warning("Unknown waterflow value received")
            return
        return {waterflow.name: waterflow.value}

    @command(click.argument("value", type=int))
    def set_waterflow(self, value: int):
        """Set water flow.

        :param int value: Water flow value to set
        """
        mapping = self._get_mapping()
        if "water_flow" not in mapping:
            return None
        waterflow = None
        try:
            waterflow = WaterFlow(value)
        except ValueError:
            _LOGGER.error(f"Unknown waterflow value passed {value}")
            return None
        click.echo(f"Setting waterflow to {waterflow.name}")
        return self.set_property("water_flow", waterflow.value)

    @command()
    def waterflow_presets(self) -> Dict[str, int]:
        """Return dictionary containing supported water flow."""
        mapping = self._get_mapping()
        if "water_flow" not in mapping:
            return {}
        return _enum_as_dict(WaterFlow)

    @command(
        click.argument("distance", default=30, type=int), )
    def forward(self, distance: int) -> None:
        """Move forward."""
        if distance < self.MANUAL_DISTANCE_MIN or distance > self.MANUAL_DISTANCE_MAX:
            raise DeviceException(
                "Given distance is invalid, should be [%s, %s], was: %s" %
                (self.MANUAL_DISTANCE_MIN, self.MANUAL_DISTANCE_MAX, distance))
        self.call_action(
            "move",
            [
                {
                    "piid": 1,
                    "value": "0",
                },
                {
                    "piid": 2,
                    "value": f"{distance}",
                },
            ],
        )

    @command(
        click.argument("rotatation", default=90, type=int), )
    def rotate(self, rotatation: int) -> None:
        """Rotate vacuum."""
        if (rotatation < self.MANUAL_ROTATION_MIN
                or rotatation > self.MANUAL_ROTATION_MAX):
            raise DeviceException(
                "Given rotation is invalid, should be [%s, %s], was %s" %
                (self.MANUAL_ROTATION_MIN, self.MANUAL_ROTATION_MAX,
                 rotatation))
        self.call_action(
            "move",
            [
                {
                    "piid": 1,
                    "value": f"{rotatation}",
                },
                {
                    "piid": 2,
                    "value": "0",
                },
            ],
        )
Example #32
0
import click

from olimage.core.parsers.packages import ParserPackages

_arguments = [
    click.argument("board"),
    click.argument("release"),
    click.argument("variant", type=click.Choice([str(v) for v in ParserPackages().variants]))
]

_options = [
    click.option("--hostname", help="Set default system hostname"),
    click.option("--keyboard-keymap", default="gb", help="Set default system keyboard locale"),
    click.option("--keyboard-layout", default="English (UK)", help="Set default system keyboard locale"),
    click.option("--locale", default="en_GB.UTF-8", help="Set default system locale"),
    click.option("--ssh/--no-ssh", default=True, help="Enable/Disable ssh access"),
    click.option("--timezone", default="Europe/London", help="Set default system timezone")
]


def parameters(func):
    for argument in reversed(_arguments):
        func = argument(func)

    for option in reversed(_options):
        func = option(func)

    return func
Example #33
0

def image_exists(image):
    # docker image accept tags only in version >= 1.8...
    # so workaround with docker history
    rc = subprocess.call("docker history -q {0} > /dev/null".format(image),
                         shell=True)
    if rc == 0:
        return True
    elif rc == 1:
        return False
    else:
        raise RuntimeError("Cannot test if image exists")


image_option = click.argument("image",
                              type=click.Choice(["centos7", "jessie"]))
salt_option = click.option('--salt', is_flag=True, help="Run salt highstate")


@click.group()
def cli():
    pass


@cli.command(help="Build a container")
@image_option
@salt_option
@click.option('--tag',
              default=None,
              help="Custom tag name for the built docker image")
@click.option('--file-root', type=click.Path(exists=True), default='test/salt')
Example #34
0
def package_arg(f):
    def callback(ctx, param, value):
        state = ctx.ensure_object(State)
        state.installstate.packages.extend(value)
        return value
    return argument('packages', nargs=-1, callback=callback, expose_value=False,)(f)
Example #35
0
import click

username_arg = click.argument("username")
cloud_alias_option = click.option(
    "--cloud-alias",
    help="If the employee has an email alias other than their Code42 username "
    "that they use for cloud services such as Google Drive, OneDrive, or Box, "
    "add and monitor the alias. WARNING: Adding a cloud alias will override any "
    "existing cloud alias for this user.",
)
notes_option = click.option("--notes",
                            help="Optional notes about the employee.")
Example #36
0
class Alarm(GatewayDevice):
    """Class representing the Xiaomi Gateway Alarm."""
    @command(default_output=format_output("[alarm_status]"))
    def status(self) -> str:
        """Return the alarm status from the device."""
        # Response: 'on', 'off', 'oning'
        return self._gateway.send("get_arming").pop()

    @command(default_output=format_output("Turning alarm on"))
    def on(self):
        """Turn alarm on."""
        return self._gateway.send("set_arming", ["on"])

    @command(default_output=format_output("Turning alarm off"))
    def off(self):
        """Turn alarm off."""
        return self._gateway.send("set_arming", ["off"])

    @command()
    def arming_time(self) -> int:
        """Return time in seconds the alarm stays 'oning' before transitioning to
        'on'."""
        # Response: 5, 15, 30, 60
        return self._gateway.send("get_arm_wait_time").pop()

    @command(click.argument("seconds"))
    def set_arming_time(self, seconds):
        """Set time the alarm stays at 'oning' before transitioning to 'on'."""
        return self._gateway.send("set_arm_wait_time", [seconds])

    @command()
    def triggering_time(self) -> int:
        """Return the time in seconds the alarm is going off when triggered."""
        # Response: 30, 60, etc.
        return self._gateway.get_prop("alarm_time_len").pop()

    @command(click.argument("seconds"))
    def set_triggering_time(self, seconds):
        """Set the time in seconds the alarm is going off when triggered."""
        return self._gateway.set_prop("alarm_time_len", seconds)

    @command()
    def triggering_light(self) -> int:
        """Return the time the gateway light blinks when the alarm is triggerd."""
        # Response: 0=do not blink, 1=always blink, x>1=blink for x seconds
        return self._gateway.get_prop("en_alarm_light").pop()

    @command(click.argument("seconds"))
    def set_triggering_light(self, seconds):
        """Set the time the gateway light blinks when the alarm is triggerd."""
        # values: 0=do not blink, 1=always blink, x>1=blink for x seconds
        return self._gateway.set_prop("en_alarm_light", seconds)

    @command()
    def triggering_volume(self) -> int:
        """Return the volume level at which alarms go off [0-100]."""
        return self._gateway.send("get_alarming_volume").pop()

    @command(click.argument("volume"))
    def set_triggering_volume(self, volume):
        """Set the volume level at which alarms go off [0-100]."""
        return self._gateway.send("set_alarming_volume", [volume])

    @command()
    def last_status_change_time(self) -> datetime:
        """Return the last time the alarm changed status."""
        return datetime.fromtimestamp(
            self._gateway.send("get_arming_time").pop())
Example #37
0
from py42.exceptions import Py42NotFoundError
from py42.exceptions import Py42UpdateClosedCaseError

from code42cli.bulk import generate_template_cmd_factory
from code42cli.bulk import run_bulk_process
from code42cli.click_ext.groups import OrderedGroup
from code42cli.errors import Code42CLIError
from code42cli.file_readers import read_csv_arg
from code42cli.options import format_option
from code42cli.options import sdk_options
from code42cli.options import set_begin_default_dict
from code42cli.options import set_end_default_dict
from code42cli.output_formats import OutputFormatter


case_number_arg = click.argument("case-number", type=int)
case_number_option = click.option(
    "--case-number", type=int, help="The number assigned to the case.", required=True
)
name_option = click.option("--name", help="The name of the case.",)
assignee_option = click.option(
    "--assignee", help="The UID of the user to assign to the case."
)
description_option = click.option("--description", help="The description of the case.")
findings_option = click.option("--findings", help="Any findings for the case.")
subject_option = click.option(
    "--subject", help="The user UID of the subject of the case."
)
status_option = click.option(
    "--status",
    help="Status of the case. `OPEN` or `CLOSED`.",
Example #38
0
def nodata_handler(ctx, param, value):
    """Get nodata value from a template file or command line."""
    retval = from_like_context(ctx, param, value)
    if retval is None and value is not None:
        try:
            retval = float(value)
        except:
            raise click.BadParameter("%s is not a number." % repr(value),
                                     param=param,
                                     param_hint='nodata')
    return retval


# Singular input file
file_in_arg = click.argument('INPUT', callback=file_in_handler)

# Singular output file
file_out_arg = click.argument('OUTPUT', type=click.Path(resolve_path=True))

bidx_opt = click.option('-b',
                        '--bidx',
                        type=int,
                        default=1,
                        help="Input file band index (default: 1).")

bidx_mult_opt = click.option('-b',
                             '--bidx',
                             multiple=True,
                             help="Indexes of input file bands.")
Example #39
0
import click
from simpletasks import Cli, Task

from gapi_helper.drive import DriveService, Folder


@click.group()
def drive():
    pass


@Cli(
    drive,
    params=[
        click.argument(
            "credentials",
            type=click.Path(exists=True, file_okay=True, dir_okay=False, readable=True, resolve_path=True),
        ),
        click.argument("user"),
    ],
)
class ListOwnedFilesTask(Task):
    def do(self) -> None:
        DriveService.configure(self.options.get("credentials"))
        user = self.options.get("user")
        delegatedService = DriveService(user).getService()

        page_token = None
        while True:
            response = (
                delegatedService.files()
                .list(
Example #40
0
class Ceil(Device):
    """Main class representing Xiaomi Philips LED Ceiling Lamp."""

    # TODO: - Auto On/Off Not Supported
    #       - Adjust Scenes with Wall Switch Not Supported

    _supported_models = SUPPORTED_MODELS

    @command(default_output=format_output(
        "",
        "Power: {result.power}\n"
        "Brightness: {result.brightness}\n"
        "Color temperature: {result.color_temperature}\n"
        "Scene: {result.scene}\n"
        "Delayed turn off: {result.delay_off_countdown}\n"
        "Smart night light: {result.smart_night_light}\n"
        "Automatic color temperature: {result.automatic_color_temperature}\n",
    ))
    def status(self) -> CeilStatus:
        """Retrieve properties."""
        properties = ["power", "bright", "cct", "snm", "dv", "bl", "ac"]
        values = self.get_properties(properties)

        return CeilStatus(defaultdict(lambda: None, zip(properties, values)))

    @command(default_output=format_output("Powering on"))
    def on(self):
        """Power on."""
        return self.send("set_power", ["on"])

    @command(default_output=format_output("Powering on"))
    def off(self):
        """Power off."""
        return self.send("set_power", ["off"])

    @command(
        click.argument("level", type=int),
        default_output=format_output("Setting brightness to {level}"),
    )
    def set_brightness(self, level: int):
        """Set brightness level."""
        if level < 1 or level > 100:
            raise CeilException("Invalid brightness: %s" % level)

        return self.send("set_bright", [level])

    @command(
        click.argument("level", type=int),
        default_output=format_output("Setting color temperature to {level}"),
    )
    def set_color_temperature(self, level: int):
        """Set Correlated Color Temperature."""
        if level < 1 or level > 100:
            raise CeilException("Invalid color temperature: %s" % level)

        return self.send("set_cct", [level])

    @command(
        click.argument("brightness", type=int),
        click.argument("cct", type=int),
        default_output=format_output(
            "Setting brightness to {brightness} and color temperature to {cct}"
        ),
    )
    def set_brightness_and_color_temperature(self, brightness: int, cct: int):
        """Set brightness level and the correlated color temperature."""
        if brightness < 1 or brightness > 100:
            raise CeilException("Invalid brightness: %s" % brightness)

        if cct < 1 or cct > 100:
            raise CeilException("Invalid color temperature: %s" % cct)

        return self.send("set_bricct", [brightness, cct])

    @command(
        click.argument("seconds", type=int),
        default_output=format_output(
            "Setting delayed turn off to {seconds} seconds"),
    )
    def delay_off(self, seconds: int):
        """Turn off delay in seconds."""

        if seconds < 1:
            raise CeilException("Invalid value for a delayed turn off: %s" %
                                seconds)

        return self.send("delay_off", [seconds])

    @command(
        click.argument("number", type=int),
        default_output=format_output("Setting fixed scene to {number}"),
    )
    def set_scene(self, number: int):
        """Set a fixed scene (1-4)."""
        if number < 1 or number > 4:
            raise CeilException("Invalid fixed scene number: %s" % number)

        return self.send("apply_fixed_scene", [number])

    @command(default_output=format_output("Turning on smart night light"))
    def smart_night_light_on(self):
        """Smart Night Light On."""
        return self.send("enable_bl", [1])

    @command(default_output=format_output("Turning off smart night light"))
    def smart_night_light_off(self):
        """Smart Night Light off."""
        return self.send("enable_bl", [0])

    @command(
        default_output=format_output("Turning on automatic color temperature"))
    def automatic_color_temperature_on(self):
        """Automatic color temperature on."""
        return self.send("enable_ac", [1])

    @command(
        default_output=format_output("Turning off automatic color temperature")
    )
    def automatic_color_temperature_off(self):
        """Automatic color temperature off."""
        return self.send("enable_ac", [0])
Example #41
0
def images_command():
    pass


OPENEDX_IMAGES = ["openedx", "forum", "notes", "xqueue", "android"]
VENDOR_IMAGES = [
    "elasticsearch",
    "memcached",
    "mongodb",
    "mysql",
    "nginx",
    "rabbitmq",
    "smtp",
]
argument_openedx_image = click.argument("image",
                                        type=click.Choice(["all"] +
                                                          OPENEDX_IMAGES))
argument_image = click.argument("image",
                                type=click.Choice(["all"] + OPENEDX_IMAGES +
                                                  VENDOR_IMAGES))


@click.command(
    short_help="Build docker images",
    help="Build the docker images necessary for an Open edX platform.",
)
@opts.root
@argument_openedx_image
@click.option("--no-cache",
              is_flag=True,
              help="Do not use cache when building the image")
Example #42
0
class AlarmClock(Device):
    """Implementation of Xiao AI Smart Alarm Clock.

    Note, this device is not very responsive to the requests, so it may take several
    seconds /tries to get an answer.
    """

    _supported_models = ["zimi.clock.myk01"]

    @command()
    def get_config_version(self):
        """
        # values unknown {'result': [4], 'id': 203}
        :return:
        """
        return self.send("get_config_version", ["audio"])

    @command()
    def clock_system(self) -> HourlySystem:
        """Returns either 12 or 24 depending on which system is in use."""
        return HourlySystem(self.send("get_hourly_system")[0])

    @command(click.argument("brightness", type=EnumType(HourlySystem)))
    def set_hourly_system(self, hs: HourlySystem):
        return self.send("set_hourly_system", [hs.value])

    @command()
    def get_button_light(self):
        """Get button's light state."""
        # ['normal', 'mute', 'offline'] or []
        return self.send("get_enabled_key_light")

    @command(click.argument("on", type=bool))
    def set_button_light(self, on):
        """Enable or disable the button light."""
        if on:
            return self.send("enable_key_light") == ["OK"]
        else:
            return self.send("disable_key_light") == ["OK"]

    @command()
    def volume(self) -> int:
        """Return the volume.

        ->  192.168.0.128 data= {"id":251,"method":"set_volume","params":[17]}
        <-  192.168.0.57 data= {"result":["OK"],"id":251}
        """
        return int(self.send("get_volume")[0])

    @command(click.argument("volume", type=int))
    def set_volume(self, volume):
        """Set volume [1,100]."""
        return self.send("set_volume", [volume]) == ["OK"]

    @command(
        click.argument("alarm_type",
                       type=EnumType(AlarmType),
                       default=AlarmType.Alarm.name))
    def get_ring(self, alarm_type: AlarmType):
        """Get current ring tone settings."""
        return RingTone(
            self.send("get_ring", [{
                "type": alarm_type.value
            }]).pop())

    @command(
        click.argument("alarm_type", type=EnumType(AlarmType)),
        click.argument("tone", type=EnumType(Tone)),
    )
    def set_ring(self, alarm_type: AlarmType, ring: RingTone):
        """Set alarm tone.

        ->  192.168.0.128 data= {"id":236,"method":"set_ring",
           "params":[{"ringtone":"a1.mp3","smart_clock":"","type":"alarm"}]}
        <-  192.168.0.57 data= {"result":["OK"],"id":236}
        """
        raise NotImplementedError()
        # return self.send("set_ring", ) == ["OK"]

    @command()
    def night_mode(self):
        """Get night mode status.

        ->  192.168.0.128 data= {"id":234,"method":"get_night_mode","params":[]}
        <-  192.168.0.57 data= {"result":[0],"id":234}
        """
        return Nightmode(self.send("get_night_mode"))

    @command()
    def set_night_mode(self):
        """Set the night mode.

        # enable
        ->  192.168.0.128 data= {"id":248,"method":"set_night_mode",
            "params":[1,"21:00","6:00"]}
        <-  192.168.0.57 data= {"result":["OK"],"id":248}

        # disable
        ->  192.168.0.128 data= {"id":249,"method":"set_night_mode",
            "params":[0,"21:00","6:00"]}
        <-  192.168.0.57 data= {"result":["OK"],"id":249}
        """
        raise NotImplementedError()

    @command()
    def near_wakeup(self):
        """Status for near wakeup.

        ->  192.168.0.128 data= {"id":235,"method":"get_near_wakeup_status",
            "params":[]}
        <-  192.168.0.57 data= {"result":["disable"],"id":235}

        # setters
        ->  192.168.0.128 data= {"id":254,"method":"set_near_wakeup_status",
            "params":["enable"]}
        <-  192.168.0.57 data= {"result":["OK"],"id":254}

        ->  192.168.0.128 data= {"id":255,"method":"set_near_wakeup_status",
            "params":["disable"]}
        <-  192.168.0.57 data= {"result":["OK"],"id":255}
        """
        return self.send("get_near_wakeup_status")

    @command()
    def countdown(self):
        """
        ->  192.168.0.128 data= {"id":258,"method":"get_count_down_v2","params":[]}
        """
        return self.send("get_count_down_v2")

    @command()
    def alarmops(self):
        """
        NOTE: the alarm_ops method is the one used to create, query and delete
        all types of alarms (reminders, alarms, countdowns).
        ->  192.168.0.128 data= {"id":263,"method":"alarm_ops",
            "params":{"operation":"create","data":[
                {"type":"alarm","event":"testlabel","reminder":"","smart_clock":0,
                "ringtone":"a2.mp3","volume":100,"circle":"once","status":"on",
                "repeat_ringing":0,"delete_datetime":1564291980000,
                "disable_datetime":"","circle_extra":"",
                "datetime":1564291980000}
                ],"update_datetime":1564205639326}}
        <-  192.168.0.57 data= {"result":[{"id":1,"ack":"OK"}],"id":263}

        # query per index, starts from 0 instead of 1 as the ids it seems
        ->  192.168.0.128 data= {"id":264,"method":"alarm_ops",
            "params":{"operation":"query","req_type":"alarm",
                "update_datetime":1564205639593,"index":0}}
        <-  192.168.0.57 data= {"result":
            [0,[
                {"i":"1","c":"once","d":"2019-07-28T13:33:00+0800","s":"on",
                "n":"testlabel","a":"a2.mp3","dd":1}
               ], "America/New_York"
            ],"id":264}

        # result [code, list of alarms, timezone]
        ->  192.168.0.128 data= {"id":265,"method":"alarm_ops",
            "params":{"operation":"query","index":0,"update_datetime":1564205639596,
                "req_type":"reminder"}}
        <-  192.168.0.57 data= {"result":[0,[],"America/New_York"],"id":265}
        """
        raise NotImplementedError()

    @command(click.argument("url"))
    def start_countdown(self, url):
        """Start countdown timer playing the given media.

        {"id":354,"method":"alarm_ops",
        "params":{"operation":"create","update_datetime":1564206432733,
        "data":[{"type":"timer",
          "background":"http://host.invalid/testfile.mp3",
          "offset":1800,
          "circle":"once",
          "volume":100,
          "datetime":1564208232733}]}}
        """

        current_ts = int(time.time() * 1000)
        payload = {
            "operation":
            "create",
            "update_datetime":
            current_ts,
            "data": [{
                "type": "timer",
                "background": "http://url_here_for_mp3",
                "offset": 30,
                "circle": "once",
                "volume": 30,
                "datetime": current_ts,
            }],
        }

        return self.send("alarm_ops", payload)

    @command()
    def query(self):
        """
        ->  192.168.0.128 data= {"id":227,"method":"alarm_ops","params":
        {"operation":"query","index":0,"update_datetime":1564205198413,"req_type":"reminder"}}

        """

        payload = {
            "operation": "query",
            "index": 0,
            "update_datetime": int(time.time() * 1000),
            "req_type": "timer",
        }
        return self.send("alarm_ops", payload)

    @command()
    def cancel(self):
        """Cancel alarm of the defined type.

        "params":{"operation":"cancel","update_datetime":1564206332603,"data":[{"type":"timer"}]}}
        """
        import time

        payload = {
            "operation": "pause",
            "update_datetime": int(time.time() * 1000),
            "data": [{
                "type": "timer"
            }],
        }
        return self.send("alarm_ops", payload)
Example #43
0
class ChuangmiPlug(Device):
    """Main class representing the Chuangmi Plug V1 and V3."""
    def __init__(self,
                 ip: str = None,
                 token: str = None,
                 start_id: int = 0,
                 debug: int = 0,
                 lazy_discover: bool = True,
                 model: str = MODEL_CHUANGMI_PLUG_M1) -> None:
        super().__init__(ip, token, start_id, debug, lazy_discover)

        if model in AVAILABLE_PROPERTIES:
            self.model = model
        else:
            self.model = MODEL_CHUANGMI_PLUG_M1

    @command(default_output=format_output(
        "", "Power: {result.power}\n"
        "USB Power: {result.usb_power}\n"
        "Temperature: {result.temperature} °C\n"
        "Load power: {result.load_power}\n"
        "WiFi LED: {result.wifi_led}\n"))
    def status(self) -> ChuangmiPlugStatus:
        """Retrieve properties."""
        properties = AVAILABLE_PROPERTIES[self.model].copy()
        values = self.send("get_prop", properties)

        properties_count = len(properties)
        values_count = len(values)
        if properties_count != values_count:
            _LOGGER.debug(
                "Count (%s) of requested properties does not match the "
                "count (%s) of received values.", properties_count,
                values_count)

        if self.model == MODEL_CHUANGMI_PLUG_V3:
            load_power = self.send("get_power", [])  # Response: [300]
            if len(load_power) == 1:
                properties.append('load_power')
                values.append(load_power[0] * 0.01)

        return ChuangmiPlugStatus(
            defaultdict(lambda: None, zip(properties, values)))

    @command(
        default_output=format_output("Powering on"), )
    def on(self):
        """Power on."""
        if self.model == MODEL_CHUANGMI_PLUG_V1:
            return self.send("set_on", [])

        return self.send("set_power", ["on"])

    @command(
        default_output=format_output("Powering off"), )
    def off(self):
        """Power off."""
        if self.model == MODEL_CHUANGMI_PLUG_V1:
            return self.send("set_off", [])

        return self.send("set_power", ["off"])

    @command(
        default_output=format_output("Powering USB on"), )
    def usb_on(self):
        """Power on."""
        return self.send("set_usb_on", [])

    @command(
        default_output=format_output("Powering USB off"), )
    def usb_off(self):
        """Power off."""
        return self.send("set_usb_off", [])

    @command(
        click.argument("wifi_led", type=bool),
        default_output=format_output(lambda wifi_led: "Turning on WiFi LED"
                                     if wifi_led else "Turning off WiFi LED"))
    def set_wifi_led(self, led: bool):
        """Set the wifi led on/off."""
        if led:
            return self.send("set_wifi_led", ["on"])
        else:
            return self.send("set_wifi_led", ["off"])
Example #44
0
class AirConditionerMiot(MiotDevice):
    """Main class representing the air conditioner which uses MIoT protocol."""

    mapping = _MAPPING

    @command(default_output=format_output(
        "",
        "Power: {result.power}\n"
        "Mode: {result.mode}\n"
        "Target Temperature: {result.target_temperature} ℃\n"
        "ECO Mode: {result.eco}\n"
        "Heater: {result.heater}\n"
        "Dryer: {result.dryer}\n"
        "Sleep Mode: {result.sleep_mode}\n"
        "Fan Speed: {result.fan_speed}\n"
        "Vertical Swing: {result.vertical_swing}\n"
        "Room Temperature: {result.temperature} ℃\n"
        "Buzzer: {result.buzzer}\n"
        "LED: {result.led}\n"
        "Electricity: {result.electricity}kWh\n"
        "Clean: {result.clean}\n"
        "Running Duration: {result.total_running_duration}\n"
        "Fan percent: {result.fan_speed_percent}\n"
        "Timer: {result.timer}\n",
    ))
    def status(self) -> AirConditionerMiotStatus:
        """Retrieve properties."""

        return AirConditionerMiotStatus({
            prop["did"]: prop["value"] if prop["code"] == 0 else None
            for prop in self.get_properties_for_mapping()
        })

    @command(default_output=format_output("Powering on"))
    def on(self):
        """Power on."""
        return self.set_property("power", True)

    @command(default_output=format_output("Powering off"))
    def off(self):
        """Power off."""
        return self.set_property("power", False)

    @command(
        click.argument("mode", type=EnumType(OperationMode)),
        default_output=format_output(
            "Setting operation mode to '{mode.value}'"),
    )
    def set_mode(self, mode: OperationMode):
        """Set operation mode."""
        return self.set_property("mode", mode.value)

    @command(
        click.argument("target_temperature", type=float),
        default_output=format_output(
            "Setting target temperature to {target_temperature}"),
    )
    def set_target_temperature(self, target_temperature: float):
        """Set target temperature in Celsius."""
        if (target_temperature < 16.0 or target_temperature > 31.0
                or target_temperature % 0.5 != 0):
            raise AirConditionerMiotException(
                "Invalid target temperature: %s" % target_temperature)
        return self.set_property("target_temperature", target_temperature)

    @command(
        click.argument("eco", type=bool),
        default_output=format_output(lambda eco: "Turning on ECO mode"
                                     if eco else "Turning off ECO mode"),
    )
    def set_eco(self, eco: bool):
        """Turn ECO mode on/off."""
        return self.set_property("eco", eco)

    @command(
        click.argument("heater", type=bool),
        default_output=format_output(lambda heater: "Turning on heater"
                                     if heater else "Turning off heater"),
    )
    def set_heater(self, heater: bool):
        """Turn aux heater mode on/off."""
        return self.set_property("heater", heater)

    @command(
        click.argument("dryer", type=bool),
        default_output=format_output(lambda dryer: "Turning on dryer"
                                     if dryer else "Turning off dryer"),
    )
    def set_dryer(self, dryer: bool):
        """Turn aux dryer mode on/off."""
        return self.set_property("dryer", dryer)

    @command(
        click.argument("sleep_mode", type=bool),
        default_output=format_output(
            lambda sleep_mode: "Turning on sleep mode"
            if sleep_mode else "Turning off sleep mode"),
    )
    def set_sleep_mode(self, sleep_mode: bool):
        """Turn sleep mode on/off."""
        return self.set_property("sleep_mode", sleep_mode)

    @command(
        click.argument("fan_speed", type=EnumType(FanSpeed)),
        default_output=format_output("Setting fan speed to {fan_speed}"),
    )
    def set_fan_speed(self, fan_speed: FanSpeed):
        """Set fan speed."""
        return self.set_property("fan_speed", fan_speed.value)

    @command(
        click.argument("vertical_swing", type=bool),
        default_output=format_output(
            lambda vertical_swing: "Turning on vertical swing"
            if vertical_swing else "Turning off vertical swing"),
    )
    def set_vertical_swing(self, vertical_swing: bool):
        """Turn vertical swing on/off."""
        return self.set_property("vertical_swing", vertical_swing)

    @command(
        click.argument("led", type=bool),
        default_output=format_output(lambda led: "Turning on LED"
                                     if led else "Turning off LED"),
    )
    def set_led(self, led: bool):
        """Turn led on/off."""
        return self.set_property("led", led)

    @command(
        click.argument("buzzer", type=bool),
        default_output=format_output(lambda buzzer: "Turning on buzzer"
                                     if buzzer else "Turning off buzzer"),
    )
    def set_buzzer(self, buzzer: bool):
        """Set buzzer on/off."""
        return self.set_property("buzzer", buzzer)

    @command(
        click.argument("percent", type=int),
        default_output=format_output("Setting fan percent to {percent}%"),
    )
    def set_fan_speed_percent(self, fan_speed_percent):
        """Set fan speed in percent, should be  between 1 to 100 or 101(auto)."""
        if fan_speed_percent < 1 or fan_speed_percent > 101:
            raise AirConditionerMiotException("Invalid fan percent: %s" %
                                              fan_speed_percent)
        return self.set_property("fan_speed_percent", fan_speed_percent)

    @command(
        click.argument("minutes", type=int),
        click.argument("delay_on", type=bool),
        default_output=format_output(
            lambda minutes, delay_on: "Setting timer to delay on after " + str(
                minutes) + " minutes" if delay_on else
            "Setting timer to delay off after " + str(minutes) + " minutes"),
    )
    def set_timer(self, minutes, delay_on):
        """Set countdown timer minutes and if it would be turned on after timeout.

        Set minutes to 0 would disable the timer.
        """
        return self.set_property(
            "timer", ",".join(["1", str(minutes),
                               str(int(delay_on))]))

    @command(
        click.argument("clean", type=bool),
        default_output=format_output(lambda clean: "Begin auto cleanning"
                                     if clean else "Abort auto cleaning"),
    )
    def set_clean(self, clean):
        """Start or abort clean mode."""
        return self.set_property("clean", str(int(clean)))
Example #45
0
class FanMiot(MiotDevice):
    def __init__(
        self,
        ip: str = None,
        token: str = None,
        start_id: int = 0,
        debug: int = 0,
        lazy_discover: bool = True,
        model: str = MODEL_FAN_P10,
    ) -> None:
        if model not in MIOT_MAPPING:
            raise FanException("Invalid FanMiot model: %s" % model)

        self.model = model

        super().__init__(MIOT_MAPPING[model], ip, token, start_id, debug,
                         lazy_discover)

    @command(default_output=format_output(
        "",
        "Power: {result.power}\n"
        "Operation mode: {result.mode}\n"
        "Speed: {result.speed}\n"
        "Oscillate: {result.oscillate}\n"
        "Angle: {result.angle}\n"
        "LED: {result.led}\n"
        "Buzzer: {result.buzzer}\n"
        "Child lock: {result.child_lock}\n"
        "Power-off time: {result.delay_off_countdown}\n",
    ))
    def status(self) -> FanStatusMiot:
        """Retrieve properties."""
        return FanStatusMiot({
            prop["did"]: prop["value"] if prop["code"] == 0 else None
            for prop in self.get_properties_for_mapping()
        })

    @command(default_output=format_output("Powering on"))
    def on(self):
        """Power on."""
        return self.set_property("power", True)

    @command(default_output=format_output("Powering off"))
    def off(self):
        """Power off."""
        return self.set_property("power", False)

    @command(
        click.argument("mode", type=EnumType(OperationMode)),
        default_output=format_output("Setting mode to '{mode.value}'"),
    )
    def set_mode(self, mode: OperationMode):
        """Set mode."""
        return self.set_property("mode", OperationModeMiot[mode.name].value)

    @command(
        click.argument("speed", type=int),
        default_output=format_output("Setting speed to {speed}"),
    )
    def set_speed(self, speed: int):
        """Set speed."""
        if speed < 0 or speed > 100:
            raise FanException("Invalid speed: %s" % speed)

        return self.set_property("fan_speed", speed)

    @command(
        click.argument("angle", type=int),
        default_output=format_output("Setting angle to {angle}"),
    )
    def set_angle(self, angle: int):
        """Set the oscillation angle."""
        if angle not in [30, 60, 90, 120, 140]:
            raise FanException(
                "Unsupported angle. Supported values: 30, 60, 90, 120, 140")

        return self.set_property("swing_mode_angle", angle)

    @command(
        click.argument("oscillate", type=bool),
        default_output=format_output(
            lambda oscillate: "Turning on oscillate"
            if oscillate else "Turning off oscillate"),
    )
    def set_oscillate(self, oscillate: bool):
        """Set oscillate on/off."""
        if oscillate:
            return self.set_property("swing_mode", True)
        else:
            return self.set_property("swing_mode", False)

    @command(
        click.argument("led", type=bool),
        default_output=format_output(lambda led: "Turning on LED"
                                     if led else "Turning off LED"),
    )
    def set_led(self, led: bool):
        """Turn led on/off."""
        if led:
            return self.set_property("light", True)
        else:
            return self.set_property("light", False)

    @command(
        click.argument("buzzer", type=bool),
        default_output=format_output(lambda buzzer: "Turning on buzzer"
                                     if buzzer else "Turning off buzzer"),
    )
    def set_buzzer(self, buzzer: bool):
        """Set buzzer on/off."""
        if buzzer:
            return self.set_property("buzzer", True)
        else:
            return self.set_property("buzzer", False)

    @command(
        click.argument("lock", type=bool),
        default_output=format_output(lambda lock: "Turning on child lock"
                                     if lock else "Turning off child lock"),
    )
    def set_child_lock(self, lock: bool):
        """Set child lock on/off."""
        return self.set_property("child_lock", lock)

    @command(
        click.argument("minutes", type=int),
        default_output=format_output(
            "Setting delayed turn off to {minutes} minutes"),
    )
    def delay_off(self, minutes: int):
        """Set delay off minutes."""

        if minutes < 0:
            raise FanException("Invalid value for a delayed turn off: %s" %
                               minutes)

        return self.set_property("power_off_time", minutes)

    @command(
        click.argument("direction", type=EnumType(MoveDirection)),
        default_output=format_output("Rotating the fan to the {direction}"),
    )
    def set_rotate(self, direction: MoveDirection):
        return self.set_property("set_move", [direction.value])
Example #46
0
                               help='Value for parameterized action.')
option_email = click.option('-e',
                            '--email',
                            multiple=True,
                            default=[],
                            metavar='EMAIL',
                            help='User email address(es).')
option_role = click.option('-r',
                           '--role',
                           multiple=True,
                           default=[],
                           metavar='ROLE',
                           help='Role name(s).')
argument_action = click.argument('action',
                                 callback=process_action,
                                 nargs=1,
                                 required=True,
                                 metavar='ACTION')
argument_user = click.argument('user',
                               callback=process_email,
                               nargs=1,
                               required=True,
                               metavar='EMAIL')
argument_role = click.argument('role',
                               callback=process_role,
                               nargs=1,
                               required=True,
                               metavar='ROLE')


#
Example #47
0
    file_list = find_files(folders, supported_formats)
    music_files = list(file_list)
    files = []

    def worker(file):
        try:
            m = File(file[1], file[0])
            files.append(m)
        except KeyboardInterrupt as e:
            logger.error(f'interrupted : {e}')
            raise
        except OSError as e:
            logger.error(e)

    Conf.parallel(worker, music_files)
    return files


folders_argument = click.argument(
    'folders',
    type=click.Path(exists=True, file_okay=False),
    nargs=-1,
    callback=config_list,
)

folder_argument = click.argument(
    'folder',
    type=click.Path(exists=True, file_okay=False),
)
Example #48
0
import click
from .click_utils import (
    CommaSeparatedText,
    Dictionary,
    valid_limit,
    valid_parameter_limits,
    mutually_exclusive_with,
    required_by,
)

COMMON_OPTIONS = {
    'input': [
        click.argument(
            'input_obj',
            metavar='<input_obj>',
            type=click.Path(exists=True, dir_okay=False),
        ),
        click.option(
            '--input-format',
            '-f',
            type=click.Choice(['anndata', 'loom']),
            default='anndata',
            show_default=True,
            help='Input object format.',
        ),
    ],
    'output': [
        click.argument(
            'output_obj',
            metavar='<output_obj>',
Example #49
0
        return from_pickle(file)

    cache_path = get_corresponding_pickle_path(path)

    if not os.path.exists(cache_path):
        click.echo(
            'The BEL script {path} has not yet been compiled. First, try running the following command:\n\n '
            'pybel compile {path}\n'.format(path=path), )
        sys.exit(1)

    return from_pickle(cache_path)


graph_pickle_argument = click.argument(
    'graph',
    metavar='path',
    type=click.File('rb'),
    callback=_from_pickle_callback,
)

graph_argument = click.argument(
    'graph',
    metavar='path',
    callback=lambda _, __, path: load(path),
)


@with_plugins(iter_entry_points('pybel.cli_plugins'))
@click.group(help="PyBEL CLI on {}".format(sys.executable))
@click.version_option()
@connection_option
@click.pass_context
Example #50
0
class AirPurifier(Device):
    """Main class representing the air purifier."""
    @command(default_output=format_output(
        "",
        "Power: {result.power}\n"
        "AQI: {result.aqi} μg/m³\n"
        "Average AQI: {result.average_aqi} μg/m³\n"
        "Temperature: {result.temperature} °C\n"
        "Humidity: {result.humidity} %\n"
        "Mode: {result.mode.value}\n"
        "LED: {result.led}\n"
        "LED brightness: {result.led_brightness}\n"
        "Illuminance: {result.illuminance} lx\n"
        "Buzzer: {result.buzzer}\n"
        "Child lock: {result.child_lock}\n"
        "Favorite level: {result.favorite_level}\n"
        "Filter life remaining: {result.filter_life_remaining} %\n"
        "Filter hours used: {result.filter_hours_used}\n"
        "Use time: {result.use_time} s\n"
        "Purify volume: {result.purify_volume} m³\n"
        "Motor speed: {result.motor_speed} rpm\n"
        "Motor 2 speed: {result.motor2_speed} rpm\n"
        "Sound volume: {result.volume} %\n"
        "Filter RFID product id: {result.filter_rfid_product_id}\n"
        "Filter RFID tag: {result.filter_rfid_tag}\n"
        "Filter type: {result.filter_type}\n"
        "Learn mode: {result.learn_mode}\n"
        "Sleep mode: {result.sleep_mode}\n"
        "Sleep time: {result.sleep_time}\n"
        "Sleep mode learn count: {result.sleep_mode_learn_count}\n"
        "AQI sensor enabled on power off: {result.auto_detect}\n",
    ))
    def status(self) -> AirPurifierStatus:
        """Retrieve properties."""

        properties = [
            "power",
            "aqi",
            "average_aqi",
            "humidity",
            "temp_dec",
            "mode",
            "favorite_level",
            "filter1_life",
            "f1_hour_used",
            "use_time",
            "motor1_speed",
            "motor2_speed",
            "purify_volume",
            "f1_hour",
            "led",
            # Second request
            "led_b",
            "bright",
            "buzzer",
            "child_lock",
            "volume",
            "rfid_product_id",
            "rfid_tag",
            "act_sleep",
            "sleep_mode",
            "sleep_time",
            "sleep_data_num",
            "app_extra",
            "act_det",
            "button_pressed",
        ]

        # A single request is limited to 16 properties. Therefore the
        # properties are divided into multiple requests
        _props = properties.copy()
        values = []
        while _props:
            values.extend(self.send("get_prop", _props[:15]))
            _props[:] = _props[15:]

        properties_count = len(properties)
        values_count = len(values)
        if properties_count != values_count:
            _LOGGER.debug(
                "Count (%s) of requested properties does not match the "
                "count (%s) of received values.",
                properties_count,
                values_count,
            )

        return AirPurifierStatus(
            defaultdict(lambda: None, zip(properties, values)))

    @command(default_output=format_output("Powering on"))
    def on(self):
        """Power on."""
        return self.send("set_power", ["on"])

    @command(default_output=format_output("Powering off"))
    def off(self):
        """Power off."""
        return self.send("set_power", ["off"])

    @command(
        click.argument("mode", type=EnumType(OperationMode, False)),
        default_output=format_output("Setting mode to '{mode.value}'"),
    )
    def set_mode(self, mode: OperationMode):
        """Set mode."""
        return self.send("set_mode", [mode.value])

    @command(
        click.argument("level", type=int),
        default_output=format_output("Setting favorite level to {level}"),
    )
    def set_favorite_level(self, level: int):
        """Set favorite level."""
        if level < 0 or level > 17:
            raise AirPurifierException("Invalid favorite level: %s" % level)

        # Possible alternative property: set_speed_favorite

        # Set the favorite level used when the mode is `favorite`,
        # should be  between 0 and 17.
        return self.send("set_level_favorite", [level])  # 0 ... 17

    @command(
        click.argument("brightness", type=EnumType(LedBrightness, False)),
        default_output=format_output("Setting LED brightness to {brightness}"),
    )
    def set_led_brightness(self, brightness: LedBrightness):
        """Set led brightness."""
        return self.send("set_led_b", [brightness.value])

    @command(
        click.argument("led", type=bool),
        default_output=format_output(lambda led: "Turning on LED"
                                     if led else "Turning off LED"),
    )
    def set_led(self, led: bool):
        """Turn led on/off."""
        if led:
            return self.send("set_led", ["on"])
        else:
            return self.send("set_led", ["off"])

    @command(
        click.argument("buzzer", type=bool),
        default_output=format_output(lambda buzzer: "Turning on buzzer"
                                     if buzzer else "Turning off buzzer"),
    )
    def set_buzzer(self, buzzer: bool):
        """Set buzzer on/off."""
        if buzzer:
            return self.send("set_buzzer", ["on"])
        else:
            return self.send("set_buzzer", ["off"])

    @command(
        click.argument("lock", type=bool),
        default_output=format_output(lambda lock: "Turning on child lock"
                                     if lock else "Turning off child lock"),
    )
    def set_child_lock(self, lock: bool):
        """Set child lock on/off."""
        if lock:
            return self.send("set_child_lock", ["on"])
        else:
            return self.send("set_child_lock", ["off"])

    @command(
        click.argument("volume", type=int),
        default_output=format_output("Setting favorite level to {volume}"),
    )
    def set_volume(self, volume: int):
        """Set volume of sound notifications [0-100]."""
        if volume < 0 or volume > 100:
            raise AirPurifierException("Invalid volume: %s" % volume)

        return self.send("set_volume", [volume])

    @command(
        click.argument("learn_mode", type=bool),
        default_output=format_output(
            lambda learn_mode: "Turning on learn mode"
            if learn_mode else "Turning off learn mode"),
    )
    def set_learn_mode(self, learn_mode: bool):
        """Set the Learn Mode on/off."""
        if learn_mode:
            return self.send("set_act_sleep", ["single"])
        else:
            return self.send("set_act_sleep", ["close"])

    @command(
        click.argument("auto_detect", type=bool),
        default_output=format_output(
            lambda auto_detect: "Turning on auto detect"
            if auto_detect else "Turning off auto detect"),
    )
    def set_auto_detect(self, auto_detect: bool):
        """Set auto detect on/off. It's a feature of the AirPurifier V1 & V3"""
        if auto_detect:
            return self.send("set_act_det", ["on"])
        else:
            return self.send("set_act_det", ["off"])

    @command(
        click.argument("value", type=int),
        default_output=format_output("Setting extra to {value}"),
    )
    def set_extra_features(self, value: int):
        """Storage register to enable extra features at the app.

        app_extra=1 unlocks a turbo mode supported feature
        """
        if value < 0:
            raise AirPurifierException("Invalid app extra value: %s" % value)

        return self.send("set_app_extra", [value])

    @command(default_output=format_output("Resetting filter"))
    def reset_filter(self):
        """Resets filter hours used and remaining life."""
        return self.send("reset_filter1")
Example #51
0
class Vacuum(Device):
    """Main class representing the vacuum."""
    def __init__(self,
                 ip: str,
                 token: str = None,
                 start_id: int = 0,
                 debug: int = 0) -> None:
        super().__init__(ip, token, start_id, debug)
        self.manual_seqnum = -1
        self.model = None
        self._fanspeeds = FanspeedV1

    @command()
    def start(self):
        """Start cleaning."""
        return self.send("app_start")

    @command()
    def stop(self):
        """Stop cleaning.

        Note, prefer 'pause' instead of this for wider support.
        Some newer vacuum models do not support this command.
        """
        return self.send("app_stop")

    @command()
    def spot(self):
        """Start spot cleaning."""
        return self.send("app_spot")

    @command()
    def pause(self):
        """Pause cleaning."""
        return self.send("app_pause")

    @command()
    def resume_or_start(self):
        """A shortcut for resuming or starting cleaning."""
        status = self.status()
        if status.in_zone_cleaning and (status.is_paused or status.got_error):
            return self.resume_zoned_clean()

        return self.start()

    @command()
    def home(self):
        """Stop cleaning and return home."""
        self.send("app_pause")
        return self.send("app_charge")

    @command(click.argument("x_coord", type=int),
             click.argument("y_coord", type=int))
    def goto(self, x_coord: int, y_coord: int):
        """Go to specific target.
        :param int x_coord: x coordinate
        :param int y_coord: y coordinate"""
        return self.send("app_goto_target", [x_coord, y_coord])

    @command(click.argument("zones", type=LiteralParamType(), required=True))
    def zoned_clean(self, zones: List):
        """Clean zones.
        :param List zones: List of zones to clean: [[x1,y1,x2,y2, iterations],[x1,y1,x2,y2, iterations]]"""
        return self.send("app_zoned_clean", zones)

    @command()
    def resume_zoned_clean(self):
        """Resume zone cleaning after being paused."""
        return self.send("resume_zoned_clean")

    @command()
    def manual_start(self):
        """Start manual control mode."""
        self.manual_seqnum = 0
        return self.send("app_rc_start")

    @command()
    def manual_stop(self):
        """Stop manual control mode."""
        self.manual_seqnum = 0
        return self.send("app_rc_end")

    MANUAL_ROTATION_MAX = 180
    MANUAL_ROTATION_MIN = -MANUAL_ROTATION_MAX
    MANUAL_VELOCITY_MAX = 0.3
    MANUAL_VELOCITY_MIN = -MANUAL_VELOCITY_MAX
    MANUAL_DURATION_DEFAULT = 1500

    @command(
        click.argument("rotation", type=int),
        click.argument("velocity", type=float),
        click.argument("duration",
                       type=int,
                       required=False,
                       default=MANUAL_DURATION_DEFAULT),
    )
    def manual_control_once(self,
                            rotation: int,
                            velocity: float,
                            duration: int = MANUAL_DURATION_DEFAULT):
        """Starts the remote control mode and executes
        the action once before deactivating the mode."""
        number_of_tries = 3
        self.manual_start()
        while number_of_tries > 0:
            if self.status().state_code == 7:
                time.sleep(5)
                self.manual_control(rotation, velocity, duration)
                time.sleep(5)
                return self.manual_stop()

            time.sleep(2)
            number_of_tries -= 1

    @command(
        click.argument("rotation", type=int),
        click.argument("velocity", type=float),
        click.argument("duration",
                       type=int,
                       required=False,
                       default=MANUAL_DURATION_DEFAULT),
    )
    def manual_control(self,
                       rotation: int,
                       velocity: float,
                       duration: int = MANUAL_DURATION_DEFAULT):
        """Give a command over manual control interface."""
        if rotation < self.MANUAL_ROTATION_MIN or rotation > self.MANUAL_ROTATION_MAX:
            raise DeviceException(
                "Given rotation is invalid, should be ]%s, %s[, was %s" %
                (self.MANUAL_ROTATION_MIN, self.MANUAL_ROTATION_MAX, rotation))
        if velocity < self.MANUAL_VELOCITY_MIN or velocity > self.MANUAL_VELOCITY_MAX:
            raise DeviceException(
                "Given velocity is invalid, should be ]%s, %s[, was: %s" %
                (self.MANUAL_VELOCITY_MIN, self.MANUAL_VELOCITY_MAX, velocity))

        self.manual_seqnum += 1
        params = {
            "omega": round(math.radians(rotation), 1),
            "velocity": velocity,
            "duration": duration,
            "seqnum": self.manual_seqnum,
        }

        self.send("app_rc_move", [params])

    @command()
    def status(self) -> VacuumStatus:
        """Return status of the vacuum."""
        return VacuumStatus(self.send("get_status")[0])

    def enable_log_upload(self):
        raise NotImplementedError("unknown parameters")
        # return self.send("enable_log_upload")

    @command()
    def log_upload_status(self):
        # {"result": [{"log_upload_status": 7}], "id": 1}
        return self.send("get_log_upload_status")

    @command()
    def consumable_status(self) -> ConsumableStatus:
        """Return information about consumables."""
        return ConsumableStatus(self.send("get_consumable")[0])

    @command(click.argument("consumable", type=Consumable))
    def consumable_reset(self, consumable: Consumable):
        """Reset consumable information."""
        return self.send("reset_consumable", [consumable.value])

    @command()
    def map(self):
        """Return map token."""
        # returns ['retry'] without internet
        return self.send("get_map_v1")

    @command(click.argument("start", type=bool))
    def edit_map(self, start):
        """Start map editing?"""
        if start:
            return self.send("start_edit_map")[0] == "ok"
        else:
            return self.send("end_edit_map")[0] == "ok"

    @command(click.option("--version", default=1))
    def fresh_map(self, version):
        """Return fresh map?"""
        if version == 1:
            return self.send("get_fresh_map")
        elif version == 2:
            return self.send("get_fresh_map_v2")
        else:
            raise VacuumException("Unknown map version: %s" % version)

    @command(click.option("--version", default=1))
    def persist_map(self, version):
        """Return fresh map?"""
        if version == 1:
            return self.send("get_persist_map")
        elif version == 2:
            return self.send("get_persist_map_v2")
        else:
            raise VacuumException("Unknown map version: %s" % version)

    @command(
        click.argument("x1", type=int),
        click.argument("y1", type=int),
        click.argument("x2", type=int),
        click.argument("y2", type=int),
    )
    def create_software_barrier(self, x1, y1, x2, y2):
        """Create software barrier (gen2 only?).

        NOTE: Multiple nogo zones and barriers could be added by passing
        a list of them to save_map.

        Requires new fw version.
        3.3.9_001633+?
        """
        # First parameter indicates the type, 1 = barrier
        payload = [1, x1, y1, x2, y2]
        return self.send("save_map", payload)[0] == "ok"

    @command(
        click.argument("x1", type=int),
        click.argument("y1", type=int),
        click.argument("x2", type=int),
        click.argument("y2", type=int),
        click.argument("x3", type=int),
        click.argument("y3", type=int),
        click.argument("x4", type=int),
        click.argument("y4", type=int),
    )
    def create_nogo_zone(self, x1, y1, x2, y2, x3, y3, x4, y4):
        """Create a rectangular no-go zone (gen2 only?).

        NOTE: Multiple nogo zones and barriers could be added by passing
        a list of them to save_map.

        Requires new fw version.
        3.3.9_001633+?
        """
        # First parameter indicates the type, 0 = zone
        payload = [0, x1, y1, x2, y2, x3, y3, x4, y4]
        return self.send("save_map", payload)[0] == "ok"

    @command(click.argument("enable", type=bool))
    def enable_lab_mode(self, enable):
        """Enable persistent maps and software barriers.

        This is required to use create_nogo_zone and create_software_barrier
        commands."""
        return self.send("set_lab_status", int(enable))["ok"]

    @command()
    def clean_history(self) -> CleaningSummary:
        """Return generic cleaning history."""
        return CleaningSummary(self.send("get_clean_summary"))

    @command()
    def last_clean_details(self) -> Optional[CleaningDetails]:
        """Return details from the last cleaning.

        Returns None if there has been no cleanups."""
        history = self.clean_history()
        if not history.ids:
            return None

        last_clean_id = history.ids.pop(0)
        return self.clean_details(last_clean_id, return_list=False)

    @command(
        click.argument("id_", type=int, metavar="ID"),
        click.argument("return_list", type=bool, default=False),
    )
    def clean_details(
        self,
        id_: int,
        return_list=True
    ) -> Union[List[CleaningDetails], Optional[CleaningDetails]]:
        """Return details about specific cleaning."""
        details = self.send("get_clean_record", [id_])

        if not details:
            _LOGGER.warning("No cleaning record found for id %s" % id_)
            return None

        if return_list:
            _LOGGER.warning("This method will be returning the details "
                            "without wrapping them into a list in the "
                            "near future. The current behavior can be "
                            "kept by passing return_list=True and this "
                            "warning will be removed when the default gets "
                            "changed.")
            return [CleaningDetails(entry) for entry in details]

        if len(details) > 1:
            _LOGGER.warning("Got multiple clean details, returning the first")

        res = CleaningDetails(details.pop())
        return res

    @command()
    def find(self):
        """Find the robot."""
        return self.send("find_me", [""])

    @command()
    def timer(self) -> List[Timer]:
        """Return a list of timers."""
        timers = list()
        timezone = pytz.timezone(self.timezone())
        for rec in self.send("get_timer", [""]):
            try:
                timers.append(Timer(rec, timezone=timezone))
            except Exception as ex:
                _LOGGER.warning("Unable to add timer for %s: %s", rec, ex)

        return timers

    @command(
        click.argument("cron"),
        click.argument("command", required=False, default=""),
        click.argument("parameters", required=False, default=""),
    )
    def add_timer(self, cron: str, command: str, parameters: str):
        """Add a timer.

        :param cron: schedule in cron format
        :param command: ignored by the vacuum.
        :param parameters: ignored by the vacuum."""
        import time

        ts = int(round(time.time() * 1000))
        return self.send("set_timer",
                         [[str(ts), [cron, [command, parameters]]]])

    @command(click.argument("timer_id", type=int))
    def delete_timer(self, timer_id: int):
        """Delete a timer with given ID.

        :param int timer_id: Timer ID"""
        return self.send("del_timer", [str(timer_id)])

    @command(click.argument("timer_id", type=int),
             click.argument("mode", type=TimerState))
    def update_timer(self, timer_id: int, mode: TimerState):
        """Update a timer with given ID.

        :param int timer_id: Timer ID
        :param TimerStae mode: either On or Off"""
        if mode != TimerState.On and mode != TimerState.Off:
            raise DeviceException("Only 'On' or 'Off' are  allowed")
        return self.send("upd_timer", [str(timer_id), mode.value])

    @command()
    def dnd_status(self):
        """Returns do-not-disturb status."""
        # {'result': [{'enabled': 1, 'start_minute': 0, 'end_minute': 0,
        #  'start_hour': 22, 'end_hour': 8}], 'id': 1}
        return DNDStatus(self.send("get_dnd_timer")[0])

    @command(
        click.argument("start_hr", type=int),
        click.argument("start_min", type=int),
        click.argument("end_hr", type=int),
        click.argument("end_min", type=int),
    )
    def set_dnd(self, start_hr: int, start_min: int, end_hr: int,
                end_min: int):
        """Set do-not-disturb.

        :param int start_hr: Start hour
        :param int start_min: Start minute
        :param int end_hr: End hour
        :param int end_min: End minute"""
        return self.send("set_dnd_timer",
                         [start_hr, start_min, end_hr, end_min])

    @command()
    def disable_dnd(self):
        """Disable do-not-disturb."""
        return self.send("close_dnd_timer", [""])

    @command(click.argument("speed", type=int))
    def set_fan_speed(self, speed: int):
        """Set fan speed.

        :param int speed: Fan speed to set"""
        # speed = [38, 60 or 77]
        return self.send("set_custom_mode", [speed])

    @command()
    def fan_speed(self):
        """Return fan speed."""
        return self.send("get_custom_mode")[0]

    def _autodetect_model(self):
        """Detect the model of the vacuum.

        For the moment this is used only for the fanspeeds,
        but that could be extended to cover other supported features."""
        try:
            info = self.info()
            self.model = info.model
        except (TypeError, DeviceInfoUnavailableException):
            # cloud-blocked vacuums will not return proper payloads
            self._fanspeeds = FanspeedV1
            self.model = ROCKROBO_V1
            _LOGGER.debug("Unable to query model, falling back to %s",
                          self._fanspeeds)
            return

        _LOGGER.info("model: %s", self.model)

        if info.model == ROCKROBO_V1:
            _LOGGER.debug("Got robov1, checking for firmware version")
            fw_version = info.firmware_version
            version, build = fw_version.split("_")
            version = tuple(map(int, version.split(".")))
            if version >= (3, 5, 7):
                self._fanspeeds = FanspeedV2
            else:
                self._fanspeeds = FanspeedV1
        elif info.model == "roborock.vacuum.e2":
            self._fanspeeds = FanspeedE2
        else:
            self._fanspeeds = FanspeedV2

        _LOGGER.debug("Using new fanspeed mapping %s for %s", self._fanspeeds,
                      info.model)

    @command()
    def fan_speed_presets(self) -> Dict[str, int]:
        """Return dictionary containing supported fan speeds."""
        if self.model is None:
            self._autodetect_model()

        return {x.name: x.value for x in list(self._fanspeeds)}

    @command()
    def sound_info(self):
        """Get voice settings."""
        return SoundStatus(self.send("get_current_sound")[0])

    @command(
        click.argument("url"),
        click.argument("md5sum"),
        click.argument("sound_id", type=int),
    )
    def install_sound(self, url: str, md5sum: str, sound_id: int):
        """Install sound from the given url."""
        payload = {"url": url, "md5": md5sum, "sid": int(sound_id)}
        return SoundInstallStatus(self.send("dnld_install_sound", payload)[0])

    @command()
    def sound_install_progress(self):
        """Get sound installation progress."""
        return SoundInstallStatus(self.send("get_sound_progress")[0])

    @command()
    def sound_volume(self) -> int:
        """Get sound volume."""
        return self.send("get_sound_volume")[0]

    @command(click.argument("vol", type=int))
    def set_sound_volume(self, vol: int):
        """Set sound volume [0-100]."""
        return self.send("change_sound_volume", [vol])

    @command()
    def test_sound_volume(self):
        """Test current sound volume."""
        return self.send("test_sound_volume")

    @command()
    def serial_number(self):
        """Get serial number."""
        serial = self.send("get_serial_number")
        if isinstance(serial, list):
            return serial[0]["serial_number"]
        return serial

    @command()
    def locale(self):
        """Return locale information."""
        return self.send("app_get_locale")

    @command()
    def timezone(self):
        """Get the timezone."""
        res = self.send("get_timezone")[0]
        if isinstance(res, dict):
            # Xiaowa E25 example
            # {'olson': 'Europe/Berlin', 'posix': 'CET-1CEST,M3.5.0,M10.5.0/3'}
            if "olson" not in res:
                raise VacuumException("Unsupported timezone format: %s" % res)

            return res["olson"]

        # Gen1 vacuum: ['Europe/Berlin']
        return res

    def set_timezone(self, new_zone):
        """Set the timezone."""
        return self.send("set_timezone", [new_zone])[0] == "ok"

    def configure_wifi(self, ssid, password, uid=0, timezone=None):
        """Configure the wifi settings."""
        extra_params = {}
        if timezone is not None:
            now = datetime.datetime.now(pytz.timezone(timezone))
            offset_as_float = now.utcoffset().total_seconds() / 60 / 60
            extra_params["tz"] = timezone
            extra_params["gmt_offset"] = offset_as_float

        return super().configure_wifi(ssid, password, uid, extra_params)

    @command()
    def carpet_mode(self):
        """Get carpet mode settings"""
        return CarpetModeStatus(self.send("get_carpet_mode")[0])

    @command(
        click.argument("enabled", required=True, type=bool),
        click.argument("stall_time", required=False, default=10, type=int),
        click.argument("low", required=False, default=400, type=int),
        click.argument("high", required=False, default=500, type=int),
        click.argument("integral", required=False, default=450, type=int),
    )
    def set_carpet_mode(
        self,
        enabled: bool,
        stall_time: int = 10,
        low: int = 400,
        high: int = 500,
        integral: int = 450,
    ):
        """Set the carpet mode."""
        click.echo("Setting carpet mode: %s" % enabled)
        data = {
            "enable": int(enabled),
            "stall_time": stall_time,
            "current_low": low,
            "current_high": high,
            "current_integral": integral,
        }
        return self.send("set_carpet_mode", [data])[0] == "ok"

    @command()
    def stop_zoned_clean(self):
        """Stop cleaning a zone."""
        return self.send("stop_zoned_clean")

    @command()
    def stop_segment_clean(self):
        """Stop cleaning a segment."""
        return self.send("stop_segment_clean")

    @command()
    def resume_segment_clean(self):
        """Resuming cleaning a segment."""
        return self.send("resume_segment_clean")

    @command(click.argument("segments", type=LiteralParamType(),
                            required=True))
    def segment_clean(self, segments: List):
        """Clean segments.
        :param List segments: List of segments to clean: [16,17,18]"""
        return self.send("app_segment_clean", segments)

    @command()
    def get_room_mapping(self):
        """Retrieves a list of segments."""
        return self.send("get_room_mapping")

    @command()
    def get_backup_maps(self):
        """Get backup maps."""
        return self.send("get_recover_maps")

    @command(click.argument("id", type=int))
    def use_backup_map(self, id: int):
        """Set backup map."""
        click.echo("Setting the map %s as active" % id)
        return self.send("recover_map", [id])

    @command()
    def get_segment_status(self):
        """Get the status of a segment."""
        return self.send("get_segment_status")

    def name_segment(self):
        raise NotImplementedError("unknown parameters")
        # return self.send("name_segment")

    def merge_segment(self):
        raise NotImplementedError("unknown parameters")
        # return self.send("merge_segment")

    def split_segment(self):
        raise NotImplementedError("unknown parameters")
        # return self.send("split_segment")

    @command()
    def waterflow(self) -> WaterFlow:
        """Get water flow setting."""
        return WaterFlow(self.send("get_water_box_custom_mode")[0])

    @command(click.argument("waterflow", type=EnumType(WaterFlow)))
    def set_waterflow(self, waterflow: WaterFlow):
        """Set water flow setting."""
        return self.send("set_water_box_custom_mode", [waterflow.value])

    @classmethod
    def get_device_group(cls):
        @click.pass_context
        def callback(ctx, *args, id_file, **kwargs):
            gco = ctx.find_object(GlobalContextObject)
            if gco:
                kwargs["debug"] = gco.debug

            start_id = manual_seq = 0
            try:
                with open(id_file, "r") as f:
                    x = json.load(f)
                    start_id = x.get("seq", 0)
                    manual_seq = x.get("manual_seq", 0)
                    _LOGGER.debug("Read stored sequence ids: %s", x)
            except (FileNotFoundError, TypeError, ValueError):
                pass

            ctx.obj = cls(*args, start_id=start_id, **kwargs)
            ctx.obj.manual_seqnum = manual_seq

        dg = DeviceGroup(
            cls,
            params=DeviceGroup.DEFAULT_PARAMS + [
                click.Option(
                    ["--id-file"],
                    type=click.Path(dir_okay=False, writable=True),
                    default=os.path.join(user_cache_dir("python-miio"),
                                         "python-mirobo.seq"),
                )
            ],
            callback=callback,
        )

        @dg.resultcallback()
        @dg.device_pass
        def cleanup(vac: Vacuum, *args, **kwargs):
            if vac.ip is None:  # dummy Device for discovery, skip teardown
                return
            id_file = kwargs["id_file"]
            seqs = {
                "seq": vac._protocol.raw_id,
                "manual_seq": vac.manual_seqnum
            }
            _LOGGER.debug("Writing %s to %s", seqs, id_file)
            path_obj = pathlib.Path(id_file)
            cache_dir = path_obj.parents[0]
            cache_dir.mkdir(parents=True, exist_ok=True)
            with open(id_file, "w") as f:
                json.dump(seqs, f)

        return dg
Example #52
0
class Heater(Device):
    """Main class representing the Smartmi Zhimi Heater."""
    def __init__(
        self,
        ip: str = None,
        token: str = None,
        start_id: int = 0,
        debug: int = 0,
        lazy_discover: bool = True,
        model: str = MODEL_HEATER_ZA1,
    ) -> None:
        super().__init__(ip, token, start_id, debug, lazy_discover)

        if model in SUPPORTED_MODELS.keys():
            self.model = model
        else:
            self.model = MODEL_HEATER_ZA1

    @command(default_output=format_output(
        "",
        "Power: {result.power}\n"
        "Target temperature: {result.target_temperature} °C\n"
        "Temperature: {result.temperature} °C\n"
        "Humidity: {result.humidity} %\n"
        "Display brightness: {result.brightness}\n"
        "Buzzer: {result.buzzer}\n"
        "Child lock: {result.child_lock}\n"
        "Power-off time: {result.delay_off_countdown}\n",
    ))
    def status(self) -> HeaterStatus:
        """Retrieve properties."""
        properties = SUPPORTED_MODELS[self.model]["available_properties"]

        # A single request is limited to 16 properties. Therefore the
        # properties are divided into multiple requests
        _props_per_request = 15

        # The MA1, ZA1 is limited to a single property per request
        if self.model in [MODEL_HEATER_MA1, MODEL_HEATER_ZA1]:
            _props_per_request = 1

        values = self.get_properties(properties,
                                     max_properties=_props_per_request)

        return HeaterStatus(dict(zip(properties, values)))

    @command(default_output=format_output("Powering on"))
    def on(self):
        """Power on."""
        return self.send("set_power", ["on"])

    @command(default_output=format_output("Powering off"))
    def off(self):
        """Power off."""
        return self.send("set_power", ["off"])

    @command(
        click.argument("temperature", type=int),
        default_output=format_output(
            "Setting target temperature to {temperature}"),
    )
    def set_target_temperature(self, temperature: int):
        """Set target temperature."""
        min_temp, max_temp = SUPPORTED_MODELS[self.model]["temperature_range"]
        if not min_temp <= temperature <= max_temp:
            raise HeaterException("Invalid target temperature: %s" %
                                  temperature)

        return self.send("set_target_temperature", [temperature])

    @command(
        click.argument("brightness", type=EnumType(Brightness)),
        default_output=format_output(
            "Setting display brightness to {brightness}"),
    )
    def set_brightness(self, brightness: Brightness):
        """Set display brightness."""
        return self.send("set_brightness", [brightness.value])

    @command(
        click.argument("buzzer", type=bool),
        default_output=format_output(lambda buzzer: "Turning on buzzer"
                                     if buzzer else "Turning off buzzer"),
    )
    def set_buzzer(self, buzzer: bool):
        """Set buzzer on/off."""
        if buzzer:
            return self.send("set_buzzer", ["on"])
        else:
            return self.send("set_buzzer", ["off"])

    @command(
        click.argument("lock", type=bool),
        default_output=format_output(lambda lock: "Turning on child lock"
                                     if lock else "Turning off child lock"),
    )
    def set_child_lock(self, lock: bool):
        """Set child lock on/off."""
        if lock:
            return self.send("set_child_lock", ["on"])
        else:
            return self.send("set_child_lock", ["off"])

    @command(
        click.argument("seconds", type=int),
        default_output=format_output(
            "Setting delayed turn off to {seconds} seconds"),
    )
    def delay_off(self, seconds: int):
        """Set delay off seconds."""
        min_delay, max_delay = SUPPORTED_MODELS[self.model]["delay_off_range"]
        if not min_delay <= seconds <= max_delay:
            raise HeaterException("Invalid delay time: %s" % seconds)

        if self.model == MODEL_HEATER_ZA1:
            return self.send("set_poweroff_time", [seconds])
        elif self.model == MODEL_HEATER_MA1:
            return self.send("set_poweroff_level", [seconds // 3600])

        return None
Example #53
0
class AirDehumidifier(Device):
    """Implementation of Xiaomi Mi Air Dehumidifier."""
    def __init__(
        self,
        ip: str = None,
        token: str = None,
        start_id: int = 0,
        debug: int = 0,
        lazy_discover: bool = True,
        model: str = MODEL_DEHUMIDIFIER_V1,
    ) -> None:
        super().__init__(ip, token, start_id, debug, lazy_discover)

        if model in AVAILABLE_PROPERTIES:
            self.model = model
        else:
            self.model = MODEL_DEHUMIDIFIER_V1

        self.device_info = None

    @command(default_output=format_output(
        "",
        "Power: {result.power}\n"
        "Mode: {result.mode}\n"
        "Temperature: {result.temperature} °C\n"
        "Humidity: {result.humidity} %\n"
        "Buzzer: {result.buzzer}\n"
        "LED : {result.led}\n"
        "Child lock: {result.child_lock}\n"
        "Target humidity: {result.target_humidity} %\n"
        "Fan speed: {result.fan_speed}\n"
        "Tank Full: {result.tank_full}\n"
        "Compressor Status: {result.compressor_status}\n"
        "Defrost Status: {result.defrost_status}\n"
        "Fan st: {result.fan_st}\n"
        "Alarm: {result.alarm}\n",
    ))
    def status(self) -> AirDehumidifierStatus:
        """Retrieve properties."""

        if self.device_info is None:
            self.device_info = self.info()

        properties = AVAILABLE_PROPERTIES[self.model]

        values = self.get_properties(properties, max_properties=1)

        return AirDehumidifierStatus(
            defaultdict(lambda: None, zip(properties, values)),
            self.device_info)

    @command(default_output=format_output("Powering on"))
    def on(self):
        """Power on."""
        return self.send("set_power", ["on"])

    @command(default_output=format_output("Powering off"))
    def off(self):
        """Power off."""
        return self.send("set_power", ["off"])

    @command(
        click.argument("mode", type=EnumType(OperationMode, False)),
        default_output=format_output("Setting mode to '{mode.value}'"),
    )
    def set_mode(self, mode: OperationMode):
        """Set mode."""
        try:
            return self.send("set_mode", [mode.value])
        except DeviceError as error:
            # {'code': -6011, 'message': 'device_poweroff'}
            if error.code == -6011:
                self.on()
                return self.send("set_mode", [mode.value])
            raise

    @command(
        click.argument("fan_speed", type=EnumType(FanSpeed, False)),
        default_output=format_output("Setting fan level to {fan_level}"),
    )
    def set_fan_speed(self, fan_speed: FanSpeed):
        """Set the fan speed."""
        return self.send("set_fan_level", [fan_speed.value])

    @command(
        click.argument("led", type=bool),
        default_output=format_output(lambda led: "Turning on LED"
                                     if led else "Turning off LED"),
    )
    def set_led(self, led: bool):
        """Turn led on/off."""
        if led:
            return self.send("set_led", ["on"])
        else:
            return self.send("set_led", ["off"])

    @command(
        click.argument("buzzer", type=bool),
        default_output=format_output(lambda buzzer: "Turning on buzzer"
                                     if buzzer else "Turning off buzzer"),
    )
    def set_buzzer(self, buzzer: bool):
        """Set buzzer on/off."""
        if buzzer:
            return self.send("set_buzzer", ["on"])
        else:
            return self.send("set_buzzer", ["off"])

    @command(
        click.argument("lock", type=bool),
        default_output=format_output(lambda lock: "Turning on child lock"
                                     if lock else "Turning off child lock"),
    )
    def set_child_lock(self, lock: bool):
        """Set child lock on/off."""
        if lock:
            return self.send("set_child_lock", ["on"])
        else:
            return self.send("set_child_lock", ["off"])

    @command(
        click.argument("humidity", type=int),
        default_output=format_output("Setting target humidity to {humidity}"),
    )
    def set_target_humidity(self, humidity: int):
        """Set the auto target humidity."""
        if humidity not in [40, 50, 60]:
            raise AirDehumidifierException("Invalid auto target humidity: %s" %
                                           humidity)

        return self.send("set_auto", [humidity])
)

HOSTNAME_PROMPT = click.option(
    "--host",
    "host",
    is_eager=False,
    prompt=True,
    callback=trim_trailing_slash,
    envvar=("C8Y_HOST", "C8Y_BASEURL", "C8Y_URL"),
    help="Cumulocity Hostname  [required] [env var: C8Y_HOST]",
)


ARG_DEVICE = click.argument(
    "device",
    nargs=1,
    required=True,
)

DEVICE = click.option(
    "--device",
    "-d",
    required=False,
    envvar="C8YLP_DEVICE",
    show_envvar=True,
    help="Device external identity",
)

EXTERNAL_IDENTITY_TYPE = click.option(
    "--external-type",
    envvar="C8YLP_EXTERNAL_TYPE",
Example #55
0
    if retval is None and value is not None:
        try:
            value = value.strip(', []')
            retval = tuple(float(x) for x in re.split(r'[,\s]+', value))
            assert len(retval) == 4
            return retval
        except Exception:
            raise click.BadParameter(
                "{0!r} is not a valid bounding box representation".format(
                    value))
    else:  # pragma: no cover
        return retval


# Singular input file
file_in_arg = click.argument('INPUT', callback=file_in_handler)

# Singular output file
file_out_arg = click.argument('OUTPUT', type=click.Path(resolve_path=True))

# Multiple input files.
files_in_arg = click.argument('files',
                              nargs=-1,
                              type=click.Path(),
                              required=True,
                              metavar="INPUTS...",
                              callback=files_in_handler)

# Multiple files, last of which is an output file.
files_inout_arg = click.argument('files',
                                 nargs=-1,
Example #56
0
class Cooker(Device):
    """Main class representing the cooker."""
    @command(default_output=format_output(
        "",
        "Mode: {result.mode}\n"
        "Menu: {result.menu}\n"
        "Stage: {result.stage}\n"
        "Temperature: {result.temperature}\n"
        "Start time: {result.start_time}\n"
        "Remaining: {result.remaining}\n"
        "Cooking delayed: {result.cooking_delayed}\n"
        "Duration: {result.duration}\n"
        "Settings: {result.settings}\n"
        "Interaction timeouts: {result.interaction_timeouts}\n"
        "Hardware version: {result.hardware_version}\n"
        "Firmware version: {result.firmware_version}\n"
        "Favorite: {result.favorite}\n"
        "Custom: {result.custom}\n",
    ))
    def status(self) -> CookerStatus:
        """Retrieve properties."""
        properties = [
            "func",
            "menu",
            "stage",
            "temp",
            "t_func",
            "t_precook",
            "t_cook",
            "setting",
            "delay",
            "version",
            "favorite",
            "custom",
        ]
        """
        Some cookers doesn't support a list of properties here. Therefore "all" properties
        are requested. If the property count or order changes the property list above must
        be updated.
        """
        values = self.send("get_prop", ["all"])

        properties_count = len(properties)
        values_count = len(values)
        if properties_count != values_count:
            _LOGGER.debug(
                "Count (%s) of requested properties does not match the "
                "count (%s) of received values.",
                properties_count,
                values_count,
            )

        return CookerStatus(defaultdict(lambda: None, zip(properties, values)))

    @command(
        click.argument("profile", type=str),
        default_output=format_output("Cooking profile started"),
    )
    def start(self, profile: str):
        """Start cooking a profile."""
        if not self._validate_profile(profile):
            raise CookerException("Invalid cooking profile: %s" % profile)

        self.send("set_start", [profile])

    @command(default_output=format_output("Cooking stopped"))
    def stop(self):
        """Stop cooking."""
        self.send("set_func", ["end02"])

    @command(default_output=format_output("Cooking stopped"))
    def stop_outdated_firmware(self):
        """Stop cooking (obsolete)."""
        self.send("set_func", ["end"])

    @command(default_output=format_output("Setting no warnings"))
    def set_no_warnings(self):
        """Disable warnings."""
        self.send("set_func", ["nowarn"])

    @command(default_output=format_output("Setting acknowledge"))
    def set_acknowledge(self):
        """Enable warnings?"""
        self.send("set_func", ["ack"])

    # FIXME: Add unified CLI support
    def set_interaction(self, settings: CookerSettings,
                        timeouts: InteractionTimeouts):
        """Set interaction. Supported by all cookers except MODEL_PRESS1"""
        self.send(
            "set_interaction",
            [
                str(settings),
                "{:x}".format(timeouts.led_off),
                "{:x}".format(timeouts.lid_open),
                "{:x}".format(timeouts.lid_open_warning),
            ],
        )

    @command(
        click.argument("profile", type=str),
        default_output=format_output("Setting menu to {profile}"),
    )
    def set_menu(self, profile: str):
        """Select one of the default(?) cooking profiles"""
        if not self._validate_profile(profile):
            raise CookerException("Invalid cooking profile: %s" % profile)

        self.send("set_menu", [profile])

    @command(default_output=format_output("",
                                          "Temperature history: {result}\n"))
    def get_temperature_history(self) -> TemperatureHistory:
        """Retrieves a temperature history.

        The temperature is only available while cooking.
        Approx. six data points per minute.
        """
        data = self.send("get_temp_history")

        return TemperatureHistory(data[0])

    @staticmethod
    def _validate_profile(profile):
        return all(c in string.hexdigits
                   for c in profile) and len(profile) in [
                       228,
                       242,
                   ]
Example #57
0
                                      help='Alternative odd config file',
                                      type=click.Path(exists=False),
                                      default=os.path.expanduser(PIUCONFIG))
option_pg_service_file = click.option('--pg_service-file',
                                      help='The PostgreSQL service file',
                                      envvar='PGSERVICEFILE',
                                      type=click.Path(exists=True))
option_region = click.option('--region',
                             envvar='AWS_DEFAULT_REGION',
                             metavar='AWS_REGION_ID',
                             help='AWS region ID (e.g. eu-west-1)')
option_reuse = click.option('--reuse/--no-reuse',
                            default=True,
                            help='Reuse an already exisiting tunnel')

cluster_argument = click.argument('cluster')


class Spilo(
        collections.namedtuple(
            'Spilo',
            'stack_name, version, dns, elb, instances, vpc_id, stack')):
    pass


@click.group(cls=AliasedGroup)
def cli():
    """
    Spilo can connect to your Spilo cluster running inside a vpc. It does this using the stups infrastructure.
    """