# `Grizzly.ZWave.CommandSpec`
[🔗](https://github.com/smartrent/grizzly/blob/v9.1.4/lib/grizzly/zwave/command_spec.ex#L1)

Data structure describing a Z-Wave command, including how to create, encode,
and decode it.

# `report_matcher`

```elixir
@type report_matcher() :: (get :: Grizzly.ZWave.Command.t(),
                     report :: Grizzly.ZWave.Command.t() -&gt;
                       boolean())
```

# `t`

```elixir
@type t() :: %Grizzly.ZWave.CommandSpec{
  command_byte: byte(),
  command_class: atom(),
  decode_fun: {module(), atom()},
  default_params: keyword(),
  encode_fun: {module(), atom()},
  handler: {module(), keyword()},
  module: module(),
  name: atom(),
  params: [{atom(), Grizzly.ZWave.ParamSpec.t()}],
  report: atom() | nil,
  report_matcher_fun: {module(), atom()} | nil,
  supports_supervision?: boolean(),
  validate_fun:
    {module(), atom()} | (keyword() -&gt; {:ok, keyword()} | {:error, any()}) | nil
}
```

* `:name` (`t:atom/0`) - Required. The command's name as an atom (should be globally unique).

* `:command_class` (`t:Grizzly.ZWave.CommandClasses.command_class/0`) - Required. The command class this command belongs to.

* `:module` (`t:atom/0`) - Required. The module implementing this command's encoding and decoding functions.

* `:command_byte` - Required. The command identifier.

* `:encode_fun` - Required. A function or `{module, function}` tuple used to encode the command's
  parameters into a binary. Only 1-arity functions are currently supported.

* `:decode_fun` - Required. A function or `{module, function}` tuple used to decode the command's
  parameters from binary to a keyword list (the reverse of the `encode_fun`).

  If the function is of arity 1, the first argument will be the binary to
  decode. If arity 2, the command spec will be inserted as the first argument.

* `:report_matcher_fun` - A 2-arity function or `{module, function}` tuple used to match a
  report command to a get command. The first argument will be the get
  command and the second argument will be the report command to match.
  The function should return `true` if the report matches the get.

* `:report` (`t:atom/0`) - The name of the report command associated with this command, if any.
  For get commands, this will default to the command name with the trailing
  `_get` replaced with `_report`. To override this behavior, explicitly
  set this field to nil.

  A special value of `:any` may be used to indicate that any report command
  can satisfy this particular get command. Otherwise, this should be
  the name of a registered report command.

* `:handler` (tuple of `t:atom/0`, `t:keyword/0` values) - A `{module, options}` tuple indicating the request handler
  that should be used to handle completion of this command when sent
  via a `Grizzly.Request`. Normally, this will default to `{AckResponse, []}`.
  However, if the `:report` option is specified but `:handler` is not,
  the default becomes `{WaitReport, complete_report: report}`.

* `:supports_supervision?` (`t:boolean/0`) - Whether this command supports Z-Wave Supervision. Defaults to `false`
  for commands whose names end with `_get`. Defaults to `true` for commands
  whose names end with `_set` or `_report`. Defaults to `false` for commands
  named `network_management_*`, as most of these are only supported by
  Z/IP Gateway. The default value is `true`.

* `:validate_fun` - A `{module, function}` tuple indicating a function that validates
  the command parameters. The function should return `{:ok, params}` if the
  parameters are valid or have been updated, or `{:error, reason}` if the
  parameters are invalid.

* `:params` - The default value is `[]`.

* `:default_params` (`t:keyword/0`) - A keyword list of default parameters for the command. These parameters
  will be merged with any parameters passed to `create_command/2` before
  validation. The default value is `[]`.

# `handler_spec`

Get the handler and options for a command.

# `new`

Create a new command spec.

# `new`

Create a new command spec.

# `validate`

Validate a command spec.

# `validate_param_list`

```elixir
@spec validate_param_list([{atom(), Grizzly.ZWave.ParamSpec.t()}]) ::
  {:ok, [{atom(), Grizzly.ZWave.ParamSpec.t()}]} | {:error, String.t()}
```

Validates a list of parameter specs.

## Examples

    iex> params = [
    ...>   param1: %Grizzly.ZWave.ParamSpec{name: :param1, type: :uint, size: 8},
    ...>   param2: %Grizzly.ZWave.ParamSpec{name: :param2, type: :int, size: 16}
    ...> ]
    iex> Grizzly.ZWave.CommandSpec.validate_param_list(params)
    {:ok, params}

    iex> params = [
    ...>   param1: %Grizzly.ZWave.ParamSpec{name: :param1, type: :uint, size: 7},
    ...>   param2: %Grizzly.ZWave.ParamSpec{name: :param2, type: :int, size: 8}
    ...> ]
    iex> Grizzly.ZWave.CommandSpec.validate_param_list(params)
    {:error, "Total size of all non-variable parameters must be a multiple of 8 bits"}

    iex> params = [
    ...>   param1: %Grizzly.ZWave.ParamSpec{name: :param1, type: :uint, size: :variable},
    ...>   param2: %Grizzly.ZWave.ParamSpec{name: :param2, type: :int, size: 16}
    ...> ]
    iex> Grizzly.ZWave.CommandSpec.validate_param_list(params)
    {:error, "Variable-length parameter without length specifier must be last"}

# `create_command`

Create a command struct from the command spec and parameters.

# `validate_params`

Validate a command's parameters according to the command spec.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
