# `Grizzly.VirtualDevices.Device`
[🔗](https://github.com/smartrent/grizzly/blob/v9.1.4/lib/grizzly/virtual_devices/device.ex#L1)

Behaviour for implementing virtual device specifics

# `device_opt`

```elixir
@type device_opt() :: {atom(), term()}
```

Optional device options that are passed with calling implemented callbacks

This can be whatever extra information the consumer might need the device to
know about when executing the callback function.

# `t`

```elixir
@type t() :: module()
```

A module that implements this behaviour

# `device_spec`

```elixir
@callback device_spec([device_opt()]) :: Grizzly.ZWave.DeviceClass.t()
```

Return the device specification

# `handle_command`

```elixir
@callback handle_command(Grizzly.ZWave.Command.t(), [device_opt()]) ::
  :ok
  | {:ok, Grizzly.ZWave.Command.t()}
  | {:notify, Grizzly.ZWave.Command.t()}
  | {:error, :timeout}
```

Handle a Z-Wave command

When handling a command you can reply, notify, or do nothing.

In Z-Wave if your device does not understand the command sent it ignores the
command. For this case you'd return `{:error, :timeout}`.

When a command is received and your device supports the command and the
command's parameters, you either respond with `:ok` or `{:ok, Command.t()}`.
Normally, when you receive a "set" command you will want to response with
`:ok`. When you receive a "get" command you will want to response the report
command like `{:ok, Command.t()}`, where the `Command.t()` is whatever command
report you want to send to the caller.

Often times, if your device reports changes that have been made due to
handling a command, you can return `{:notify, Command.t()}`.

# `set_device_id`

```elixir
@callback set_device_id(pid(), Grizzly.VirtualDevices.id()) :: :ok
```

Set the virtual device's id once added to the (virtual) Z-Wave network.

---

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