{"id":21512290,"url":"https://github.com/smartrent/grizzly","last_synced_at":"2025-05-16T12:01:50.381Z","repository":{"id":37822232,"uuid":"189450801","full_name":"smartrent/grizzly","owner":"smartrent","description":"Elixir Z-Wave Library","archived":false,"fork":false,"pushed_at":"2025-05-02T16:13:38.000Z","size":2867,"stargazers_count":91,"open_issues_count":3,"forks_count":9,"subscribers_count":31,"default_branch":"main","last_synced_at":"2025-05-12T23:44:16.611Z","etag":null,"topics":["elixir","home-automation","iot","z-wave"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/grizzly","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smartrent.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-05-30T16:55:16.000Z","updated_at":"2025-05-02T16:13:40.000Z","dependencies_parsed_at":"2023-02-19T10:46:05.288Z","dependency_job_id":"3f93e00b-3ffa-4c61-95e8-640bd7bed190","html_url":"https://github.com/smartrent/grizzly","commit_stats":null,"previous_names":[],"tags_count":185,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartrent%2Fgrizzly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartrent%2Fgrizzly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartrent%2Fgrizzly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartrent%2Fgrizzly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smartrent","download_url":"https://codeload.github.com/smartrent/grizzly/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254527073,"owners_count":22085917,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","home-automation","iot","z-wave"],"created_at":"2024-11-23T22:31:45.283Z","updated_at":"2025-05-16T12:01:50.363Z","avatar_url":"https://github.com/smartrent.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Grizzly [![CircleCI](https://circleci.com/gh/smartrent/grizzly.svg?style=svg)](https://circleci.com/gh/smartrent/grizzly) [![Hex.pm](https://img.shields.io/hexpm/v/grizzly?style=flat-square)](https://hex.pm/packages/grizzly)\n\nAn Elixir library for Z-Wave.\n\n## Installation\n\n```elixir\ndef deps do\n  [\n    {:grizzly, \"~\u003e 5.2\"}\n  ]\nend\n```\n\n## Hardware Requirements\n\n- Z-Wave Bridge Controller\n  - [Z-Wave 500](https://www.digikey.com/products/en?mpart=ACC-UZB3-U-BRG\u0026v=336)\n  - [Z-Wave 700](https://www.digikey.com/product-detail/en/silicon-labs/SLUSB001A/336-5899-ND/9867108)\n- Compatible System\n  - [Nerves Compatible System](https://hexdocs.pm/nerves/targets.html#content)\n  - [zipgateway-env](https://github.com/mattludwigs/zipgateway-env)\n- [Silicon Labs zipgateway binary](https://www.silabs.com/products/development-tools/software/z-wave/controller-sdk/z-ip-gateway-sdk)\n\nThe `zipgateway` binary allows Grizzly to use Z-Wave over IP or Z/IP. Using the\n`zipgateway` binary provided by Silicon labs allows Grizzly to support the full\nrange of Z-Wave features quickly and reliability. Some of the more advanced\nfeatures like S2 security and smart start are already supported in Grizzly.\n\nSee instructions below for compiling the `zipgateway` binary and/or running locally.\n\nIf you want a quick reference to common uses of Grizzly see the `cookbook` docs.\n\n## Basic Usage\n\nGrizzly exposes a supervisor `Grizzly.Supervisor` for the consuming application\nto add to its supervisor tree. This gives the most flexibility and control over\nwhen Grizzly's processes start. Common ways to start Grizzly can look like:\n\n```elixir\n# all the default options are fine\nGrizzly.Supervisor.start_link()\n\n# using custom hardware where the serial port is different than the default\n# the default serial port is /dev/ttyUSB0.\nGrizzly.Supervisor.start_link(serial_port: \"/dev/ttyS4\")\n\n# if your system is using zipgateway-env and/or something other than Grizzly\n# will start and manage running the zipgateway binary\nGrizzly.Supervisor.start_link(run_zipgateway: false)\n```\n\nThere are other configuration options you can pass to Grizzly but the above are\nmost common options. The `Grizzly.Supervisor` docs explains all the options in\nmore detail.\n\nTo use a device you have to add it to the Z-Wave network. This is \"called\nincluding a device\" or \"starting an inclusion.\" While most of the Grizzly's API\nis synchronous the process of adding a node is not. So, if you are working from\nthe IEx console you can use flush to see the newly add device. Here's how this\nprocess roughly goes.\n\n```elixir\niex\u003e Grizzly.Inclusions.add_node()\n:ok\niex\u003e flush\n{:grizzly, :report,  %Grizzly.Report{\n  command: %Grizzly.ZWave.Command{\n    name: :node_add_status,\n    params: [\u003cnode info in here\u003e]\n  }\n}}\n```\n\nTo remove a device we have to do an exclusion. Z-Wave uses the umbrella term\n\"inclusions\" for both adding a removing a device, but an \"inclusion\" is only\nabout device pairing and \"exclusion\" is only about device removal. The way to\nremove the device from your network in IEx:\n\n```elixir\niex\u003e Grizzly.Inclusions.remove_node()\n:ok\niex\u003e flush\n{:grizzly, :report,  %Grizzly.Report{\n  command: %Grizzly.ZWave.Command{\n    name: :node_remove_status,\n    params: [\u003cnode info in here\u003e]\n  }\n}}\n```\n\nThere are more details about this process and how to better tie into the\nGrizzly runtime for this events in `Grizzly.Inclusions`.\n\nAfter you included a node it will be given a node id that you can use to send\nZ-Wave commands to it. Say for example we added an on off switch to our\nnetwork, in Z-Wave this will be called a binary switch, and it was given the id\nof `5`. Turning it off and on would look like this in IEx:\n\n```elixir\niex\u003e Grizzly.send_command(5, :switch_binary_set, target_value: :on)\n{:ok, %Grizzly.Report{}}\niex\u003e Grizzly.send_command(5, :switch_binary_set, target_value: :off)\n{:ok, %Grizzly.Report{}}\n```\n\nFor more documentation on what `Grizzly.send_command/4` can return see the\n`Grizzly` and `Grizzly.Report` module documentation.\n\n### Successful Commands\n\n1. `{:ok, %Grizzly.Report{type: :ack_response}}` - normally for setting things\n   on a device or changing the device's state\n1. `{:ok, %Grizzly.Report{type: :command}}` - this is normally returned when asking\n   for a device state or about some information about a device or Z-Wave\n   network. The command be access by the `:command` field field of the report.\n1. `{:ok, %Grizzly.Report{type: :queued}}` - some devices sleep, so sending a\n   command to it will be queued for some amount of type that can be access in\n   the `:queued_delay` field. Once a device wakes up the calling process will\n   receive the messages in this form: `{:grizzly, :report, %Grizzly.Report{}}`\n   where the type can either be `:queued_ping` or `:command`. To check if the\n   report you receive was queued you can check the `:queued` field in the\n   report.\n1. `{:ok, %Grizzly.Report{type: :timeout}}` - the command was sent but for some\n   reason this commanded timed out.\n\n### When things go wrong\n\n1. `{:error, :nack_response}` - for when the node is not responding to the\n   command. Grizzly has automatic retries, so if you got this message that\n   might mean the node is reachable, your Z-Wave network is experiencing a of\n   traffic, or the node has recently been hit with a lot of commands and\n   cannot handle anymore at this moment.\n1. `{:error, :including}` - the Z-Wave controller is currently in the inclusion\n   state and the controller cannot send any commands currently\n1. `{:error, :firmware_updating}` - the Z-Wave controller is currently in the\n   process of having it's firmware updated and is not able to send commands\n\nMore information about `Grizzly.send_command/4` and the options like timeouts\nand retries that can be passed to see the `Grizzly` module.\n\nMore information about reports see the documentation in the `Grizzly.Report`\nmodule.\n\n## Unsolicited Messages\n\nWhen reports are sent from the Z-Wave network to the controller without the\ncontroller asking for a report these are called unsolicited messages. A concrete\nexample of this is when you manually unlock a lock, the controller will receive\na message from the device if the associations are setup correctly (see\n`Grizzly.Node.set_lifeline_association/2` for more information). You can listen\nfor these reports using one of the following functions:\n\n- `Grizzly.subscribe_command/1`\n- `Grizzly.subscribe_commands/1`\n- `Grizzly.subscribe_node/1`\n- `Grizzly.subscribe_nodes/1`\n\n```elixir\nGrizzly.subscribe_command(:door_lock_operation_report)\n\n# manually unlock a lock\n\nflush\n\n{:grizzly, :report, %Grizzly.Report{type: :unsolicited}}\n```\n\nTo know what reports a device sends please see the device's user manual as these\nevents will be outlined by the manufacture in the manual.\n\n## Supported Command Classes\n\n| Command Class                   | Version | Notes                              |\n|---------------------------------|--------:|------------------------------------|\n| Alarm (Notification)            |       8 |                                    |\n| Anti-theft                      |       3 |                                    |\n| Anti-theft Unlock               |       1 |                                    |\n| Application Status              |       1 |                                    |\n| Association                     |       3 |                                    |\n| Association Group Info          |       3 |                                    |\n| Barrier Operator                |       1 |                                    |\n| Basic                           |       2 |                                    |\n| Battery                         |       3 |                                    |\n| Binary Sensor                   |      2* | Partial support, obsoleted by spec |\n| Binary Switch                   |       2 |                                    |\n| Central Scene                   |       3 |                                    |\n| Clock                           |       1 |                                    |\n| Configuration                   |       4 |                                    |\n| CRC-16 Encapsulation            |       1 |                                    |\n| Device Reset Locally            |       1 |                                    |\n| Door Lock                       |       4 |                                    |\n| Firmware Update MD              |       7 |                                    |\n| Hail                            |       1 |                                    |\n| Indicator                       |       4 |                                    |\n| Mailbox                         |       2 |                                    |\n| Manufacturer-specific           |       2 |                                    |\n| Meter                           |       1 |                                    |\n| Multi-channel                   |       4 |                                    |\n| Multi-channel association       |       4 |                                    |\n| Multi-command                   |       1 |                                    |\n| Multilevel Sensor               |     11* | Partial support                    |\n| Multilevel Switch               |       4 |                                    |\n| NM Basic Node                   |       2 |                                    |\n| NM Inclusion                    |       4 |                                    |\n| NM Installation and Maintenance |       4 |                                    |\n| NM Proxy                        |      3* | Partial support for v4             |\n| No Operation                    |       1 |                                    |\n| Node Naming and Location        |       1 |                                    |\n| Node Provisioning               |       1 |                                    |\n| Powerlevel                      |       1 |                                    |\n| Scene Activation                |       1 |                                    |\n| Scene Actuator Configuration    |       1 |                                    |\n| Schedule Entry Lock             |       3 |                                    |\n| Security                        |      1* | Partial support                    |\n| Security 2                      |      1* | Partial support                    |\n| Sound Switch                    |       2 |                                    |\n| Supervision                     |       2 |                                    |\n| Thermostat Fan Mode             |       1 |                                    |\n| Thermostat Fan State            |       2 |                                    |\n| Thermostat Mode                 |       2 |                                    |\n| Thermostat Operating State      |       1 |                                    |\n| Thermostat Setback              |       1 |                                    |\n| Thermostat Setpoint             |      3* | Partial support                    |\n| Time Parameters                 |       1 |                                    |\n| Time                            |       2 |                                    |\n| User Code                       |       2 |                                    |\n| Version                         |       3 |                                    |\n| Wake Up                         |       3 |                                    |\n| Window Covering                 |       1 |                                    |\n| Z/IP Gateway                    |      1* | Partial support                    |\n| Z/IP                            |       5 |                                    |\n| Z-Wave Plus Info                |       2 |                                    |\n\n## Get Started\n\n### Quick and Fast running locally\n\nIf you want to run Grizzly locally for development and/or learning before going\nthrough the challenge of compiling and running in Nerves we recommend the\n[zipgateway-env](https://github.com/mattludwigs/zipgateway-env) project. This\nprovides a docker container and CLI for compiling and running different\nversions of `zipgateway`.\n\n### Nerves Devices (WIP)\n\nFirst download the [Z/IP GW\nSDK](https://www.silabs.com/products/development-tools/software/z-wave/controller-sdk/z-ip-gateway-sdk)\nfrom Silicon Labs. You'll need to create an account with them to do this, but\nthe download is free.\n\nThe default binaries that come with the download will not work by default in\nNerves system, so you will need to compile the source for your target. The\nsource code can be found in the `Source` directory.\n\nThis can be tricky and the instructions are a work in progress, so for now\nplease contact us if you any troubles.\n\n### Connecting zipgateway to Grizzly\n\n`zipgateway` runs as a separate server, accessed over a DTLS (UDP over SSL)\nconnection. Grizzly will automatically start this server. It assumes the\nexecutable is in `/usr/sbin/zipgateway`. If this is not the case, you can\nspecify the actual location with\n\n```elixir\nconfig :grizzly,\n  zipgateway_path: \"«path»\"\n```\n\nGrizzly uses the `taptun` module to manage the TCP connection: it checks that\nthis is loaded as it starts.\n\n#### Configuring zipgateway\n\nThe `zipgateway` binary is passed a configuration file named `zipgateway.cfg`.\nThis has configuration parameters around networking and setting device specific\ninformation. Most of these configuration settings are static, so Grizzly can\nhandle those for you in a reliable way. However, there are few exposed\nconfiguration options to allow some customization around device specific\ninformation, logging, and network interface set up.\n\nSupported configuration fields are documented in `t:Grizzly.Supervisor.arg/0`.\n\nFor the most part if you are using Grizzly to run zipgateway the defaults should\njust work.\n\nWhen going through certification you will need provide some device specific\ninformation:\n\n```elixir\nconfig :grizzly,\n  zipgateway_cfg: %{\n    manufacturer_id: 0,\n    product_type: 1,\n    product_id: 1,\n    hardware_version: 1\n  }\n```\n\nThe `manufacturer_id` will be given to you by Silicon Labs, and will default\nto `0`if not set (this is `zipgateway` level default).\n\nThe above fields have no impact on the Grizzly runtime, and are only useful for\ncertification processes.\n\nWhen running `zipgateway` binary out side of Grizzly this configuration field is ignored\nand you will need to pass in the location to your configuration like so:\n\n`zipgateway -c /path/to/zipgateway.cfg`\n\n## Virtual devices\n\nGrizzly provides a way to work with virtual devices. These devices should work\nas their hardware counterparts, however, the state of these devices are held in\nmemory.\n\nGrizzly provides to example virtual devices:\n\n1. `Grizzly.VirtualDevices.Thermostat`\n1. `Grizzly.VirtualDevices.TemperatureSensor`\n\nTo use These virtual devices you will have to start them using the\n`start_link/1` call. These are not supervised by Grizzly, so you will need to\nadd them to your supervision tree. The reason for this is to provide the maximum\nflexibility to the consumer application in terms of how processes are started\nand supervised.\n\nAfter starting the device you can call the `Grizzly.send_command/4` function to\nsend the device a command.\n\n```elixir\n{:ok, _pid} = Grizzly.VirtualDevices.Thermostat.start_link([])\n{:ok, [{:virtual, _id} = virtual_device_id]} = Grizzly.Network.get_all_node_ids()\n\nGrizzly.send_command(virtual_device_id, :thermostat_setpoint_get)\n```\n\nVirtual device ids are tuples where the first item is the atom `:virtual` and\nthe second item an integer of the device id, for example:\n`{:virtual, device_id}`. Grizzly provides a guard and a helper function for any\nchecking you might have to do:\n\n1. `Grizzly.is_virtual_device/1` (guard)\n1. `Grizzly.virtual_device?/1` (function)\n\nAlso, the documentation for functions in `Grizzly.Node` and `Grizzly.Network`\nshould indicate if they work with virtual devices.\n\n## Resources\n\n- [Z-Wave Specification Documentation](https://www.silabs.com/products/wireless/mesh-networking/z-wave/specification)\n- [Z-Wave Learning Resources](https://www.silabs.com/products/wireless/learning-center/mesh-networking/z-wave)\n- [Specific Z-Wave product information](https://products.z-wavealliance.org/regions)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartrent%2Fgrizzly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmartrent%2Fgrizzly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartrent%2Fgrizzly/lists"}