SkillAgentSearch skills...

Grizzly

Elixir Z-Wave Library

Install / Use

/learn @smartrent/Grizzly
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Grizzly CircleCI Hex.pm

An Elixir library for Z-Wave.

Installation

def deps do
  [
    {:grizzly, "~> 5.2"}
  ]
end

Hardware Requirements

The zipgateway binary allows Grizzly to use Z-Wave over IP or Z/IP. Using the zipgateway binary provided by Silicon labs allows Grizzly to support the full range of Z-Wave features quickly and reliability. Some of the more advanced features like S2 security and smart start are already supported in Grizzly.

See instructions below for compiling the zipgateway binary and/or running locally.

If you want a quick reference to common uses of Grizzly see the cookbook docs.

Basic Usage

Grizzly exposes a supervisor Grizzly.Supervisor for the consuming application to add to its supervisor tree. This gives the most flexibility and control over when Grizzly's processes start. Common ways to start Grizzly can look like:

# all the default options are fine
Grizzly.Supervisor.start_link()

# using custom hardware where the serial port is different than the default
# the default serial port is /dev/ttyUSB0.
Grizzly.Supervisor.start_link(serial_port: "/dev/ttyS4")

# if your system is using zipgateway-env and/or something other than Grizzly
# will start and manage running the zipgateway binary
Grizzly.Supervisor.start_link(run_zipgateway: false)

There are other configuration options you can pass to Grizzly but the above are most common options. The Grizzly.Supervisor docs explains all the options in more detail.

To use a device you have to add it to the Z-Wave network. This is "called including a device" or "starting an inclusion." While most of the Grizzly's API is synchronous the process of adding a node is not. So, if you are working from the IEx console you can use flush to see the newly add device. Here's how this process roughly goes.

iex> Grizzly.Inclusions.add_node()
:ok
iex> flush
{:grizzly, :report,  %Grizzly.Report{
  command: %Grizzly.ZWave.Command{
    name: :node_add_status,
    params: [<node info in here>]
  }
}}

To remove a device we have to do an exclusion. Z-Wave uses the umbrella term "inclusions" for both adding a removing a device, but an "inclusion" is only about device pairing and "exclusion" is only about device removal. The way to remove the device from your network in IEx:

iex> Grizzly.Inclusions.remove_node()
:ok
iex> flush
{:grizzly, :report,  %Grizzly.Report{
  command: %Grizzly.ZWave.Command{
    name: :node_remove_status,
    params: [<node info in here>]
  }
}}

There are more details about this process and how to better tie into the Grizzly runtime for this events in Grizzly.Inclusions.

After you included a node it will be given a node id that you can use to send Z-Wave commands to it. Say for example we added an on off switch to our network, in Z-Wave this will be called a binary switch, and it was given the id of 5. Turning it off and on would look like this in IEx:

iex> Grizzly.send_command(5, :switch_binary_set, target_value: :on)
{:ok, %Grizzly.Report{}}
iex> Grizzly.send_command(5, :switch_binary_set, target_value: :off)
{:ok, %Grizzly.Report{}}

For more documentation on what Grizzly.send_command/4 can return see the Grizzly and Grizzly.Report module documentation.

Successful Commands

  1. {:ok, %Grizzly.Report{type: :ack_response}} - normally for setting things on a device or changing the device's state
  2. {:ok, %Grizzly.Report{type: :command}} - this is normally returned when asking for a device state or about some information about a device or Z-Wave network. The command be access by the :command field field of the report.
  3. {:ok, %Grizzly.Report{type: :queued}} - some devices sleep, so sending a command to it will be queued for some amount of type that can be access in the :queued_delay field. Once a device wakes up the calling process will receive the messages in this form: {:grizzly, :report, %Grizzly.Report{}} where the type can either be :queued_ping or :command. To check if the report you receive was queued you can check the :queued field in the report.
  4. {:ok, %Grizzly.Report{type: :timeout}} - the command was sent but for some reason this commanded timed out.

When things go wrong

  1. {:error, :nack_response} - for when the node is not responding to the command. Grizzly has automatic retries, so if you got this message that might mean the node is reachable, your Z-Wave network is experiencing a of traffic, or the node has recently been hit with a lot of commands and cannot handle anymore at this moment.
  2. {:error, :including} - the Z-Wave controller is currently in the inclusion state and the controller cannot send any commands currently
  3. {:error, :firmware_updating} - the Z-Wave controller is currently in the process of having it's firmware updated and is not able to send commands

More information about Grizzly.send_command/4 and the options like timeouts and retries that can be passed to see the Grizzly module.

More information about reports see the documentation in the Grizzly.Report module.

Unsolicited Messages

When reports are sent from the Z-Wave network to the controller without the controller asking for a report these are called unsolicited messages. A concrete example of this is when you manually unlock a lock, the controller will receive a message from the device if the associations are setup correctly (see Grizzly.Node.set_lifeline_association/2 for more information). You can listen for these reports using Grizzly.subscribe/2.

Grizzly.subscribe_command(:door_lock_operation_report)

# manually unlock a lock

flush

{:grizzly, :report, %Grizzly.Report{type: :unsolicited}}

To know what reports a device sends please see the device's user manual as these events will be outlined by the manufacture in the manual.

Supported Command Classes

| Command Class | Version | Notes | |---------------------------------|--------:|------------------------------------| | Alarm (Notification) | 8 | | | Anti-theft | 3 | | | Anti-theft Unlock | 1 | | | Application Status | 1 | | | Association | 3 | | | Association Group Info | 3 | | | Barrier Operator | 1 | | | Basic | 2 | | | Battery | 3 | | | Binary Sensor | 2* | Partial support, obsoleted by spec | | Binary Switch | 2 | | | Central Scene | 3 | | | Clock | 1 | | | Configuration | 4 | | | CRC-16 Encapsulation | 1 | | | Device Reset Locally | 1 | | | Door Lock | 4 | | | Firmware Update MD | 7 | | | Hail | 1 | | | Indicator | 4 | | | Manufacturer-specific | 2 | | | Meter | 1 | | | Multi-channel | 4 | | | Multi-channel association | 4 | | | Multi-command | 1 | | | Multilevel Sensor | 11* | Partial support | | Multilevel Switch | 4 | | | NM Basic Node | 2 | | | NM Inclusion | 4 | | | NM Installation and Maintenance | 4 | | | NM Proxy | 3* | Partial support for v4 | | No Operation | 1 | | | Node Naming and Location | 1 | | | Node Provisioning | 1 | | | Powerlevel | 1 | | | Scene Activation | 1 | | | Scene Actuator Configuration | 1 | | | Schedule Entry Lock | 3 | | | S

View on GitHub
GitHub Stars92
CategoryDevelopment
Updated9d ago
Forks8

Languages

Elixir

Security Score

100/100

Audited on Mar 23, 2026

No findings