View Source Grizzly.Inclusions (grizzly v8.5.3)
Module for adding and removing Z-Wave nodes
In Z-Wave the term "inclusions" means two things:
- Adding a new Z-Wave device to the Z-Wave Network
- Removing a Z-Wave device to the Z-Wave Network
In practice though it is more common to speak about adding a Z-Wave node in the context of "including" and removing an Z-Wave mode in the context of "excluding." This module provides functionality for working will all contexts of inclusion, both adding and removing.
Adding a Z-Wave Node (including)
When adding a device that does not required any security authentication is
as simple as calling Grizzly.Inclusions.add_node/0
.
iex> Grizzly.Inclusions.add_node()
:ok
After starting the inclusion on the controller, which the above function
does, you can then put your device into inclusion as well. From here the new
device and your controller will communicate and if all goes well you should
receive a message in the form of
{:grizzly, :inclusion, NodeAddStatus}
where the the NodeAddStatus
is a
Z-Wave command the contains information about the inclusion status (status,
node id, supported command classes, security levels, etc.). See
Grizzly.ZWave.Commands.NodeAddStatus
for more information about the values
in that command. For example:
defmodule MyInclusionServer do
use GenServer
require Logger
alias Grizzly.Inclusions
alias Grizzly.ZWave.Command
def start_link(_) do
GenServer.start_link(__MODULE__, nil)
end
def add_node(pid) do
GenServer.call(pid, :add_node)
end
def init(_) do
{:ok, nil}
end
def handle_call(:add_node, _from, state) do
:ok = Inclusions.add_node()
{:reply, :ok, state}
end
def handle_info({:grizzly, :inclusion, report}, state) do
case Command.param!(report.command, :status) do
:done ->
node_id = Command.param!(report.command, :node_id)
Logger.info("Node added with id: " <> node_id)
:failed ->
Logger.warning("Adding node failed :(")
:security_failed ->
node_id = Command.param!(report.command, :node_id)
Logger.warning("Node added with id: " <> node_id <> "but the security failed")
end
{:noreply, state}
end
end
Stop Adding a Node
If you need you need to stop trying to add a node to the Z-Wave network you
can use the Grizzly.Inclusions.remove_node/0
function.
This should stop the controller from trying to add a node and return it to a normal functions state.
Security
There are five security levels in Z-Wave: unsecured, S0, S2 unauthenticated, S2 authenticated, and S2 access control. The first 2 requires nothing special from the calling process to able to use, as the controller and the including node will figure out which security scheme to use.
S2
The process of adding an S2 device is a little more involved. The process is
the same up until right after you put the including node into the inclusion
mode. At that point including will request security keys, which really means
it tells you which S2 security scheme it supports. You then use the
Grizzly.Inclusions.grant_keys/1
function to pass a list of allowed security
schemes.
After that the node will response with a NodeAddDSKReport
where it reports
the DSK and something called the :dsk_input_length
. If the input length is
0
, that means it is trying to do S2 unauthenticated inclusion. You can
just call Grizzly.Inclusions.set_input_dsk/0
function and the rest of the
inclusion process should continue until complete.
If the :dsk_input_length
has number, normally will be 2
that means the
including device is requesting a 5 digit digit pin that is normally found on
a label somewhere on the physical device it.
From here you can call Grizzly.Inclusions.set_input_dsk/1
with the 5 digit
integer as the argument. The inclusion process should continue until complete.
Removing a Z-Wave Node (excluding)
To remove a Z-Wave node from the network the
Grizzly.Inclusions.remove_node/0
will start an inclusion process for removing
a Z-Wave node. After calling this function you can place your device into the
inclusion (normally the same way you included the device is the way the device
is excluded) mode. At the end of the exclusion the NodeRemoveStatus
command
is received and can be inspected for success of failure.
Removed Node ID 0?
Any Z-Wave controller can excluded a device from another controller. In practice this means your Z-Wave controller can make a device "forget" the controller it is currently attached to. Most the time Z-Wave products will have you excluded your device and then included just to make sure the including node isn't connected to another Z-Wave controller.
When this happens you will a successful NodeRemoveStatusReport
but the node
id will be 0
. This is consider successful and most the time intend.
Stopping Remove Node Process
To stop the removal inclusion process on your controller you can call the
Grizzly.Inclusions.remove_node_stop/0
function.
Inclusion Handler
To tie into the inclusion process we default to sending messages to the calling process. However, there is a better way to tie into this system.
When starting any inclusion process you can pass the :handler
option
which can be either another pid or a module that implements the
Grizzly.InclusionHandler
behaviour, or a tuple with the module and callback arguments.
A basic implementation might look like:
defmodule MyApp.InclusionHandler do
@behaviour Grizzly.InclusionHandler
require Logger
def handle_report(report, opts) do
Logger.info("Got command: " <> report.command.name <> " with callback arguments " <> inspect opts)
:ok
end
end
This is recommended for applications using Grizzly over a GenServer
that
wraps Grizzly.Inclusions
.
Summary
Functions
Start the process to add a Z-Wave node to the network
Stop an add node inclusion process
Tell the inclusion process which keys to use during the inclusion process
Check to see if there is an inclusion process running
Start learn mode on the controller
Stop learn mode on the controller
Start the process to remove a Z-Wave node from the network
Stop a remove node inclusion process
Tell the inclusion process what the input DSK is
Get the current status of the inclusion process
Stop the inclusion runner
Types
@type opt() :: {:controller_id, Grizzly.node_id()} | {:timeout, non_neg_integer()} | {:handler, pid() | module() | {module(), keyword()}} | {atom(), term()}
Options for inclusion
@type status() ::
:idle
| :node_adding
| :node_add_stopping
| :node_removing
| :node_remove_stopping
| :waiting_dsk
| :waiting_s2_keys
| :s2_keys_granted
| :dsk_input_set
| :learn_mode
| :learn_mode_stopping
Status of the inclusion server
Functions
Start the process to add a Z-Wave node to the network
@spec add_node_stop() :: :ok | status()
Stop an add node inclusion process
@spec grant_keys([Grizzly.ZWave.Security.key()]) :: :ok | status()
Tell the inclusion process which keys to use during the inclusion process
During S2 inclusion the node being included with send a DSKAddKeysReport
to request which keys it can use to included securely. This function is
useful for passing back to the node which keys it is allowed to use and
depending on that answer the including node might request more information.
@spec inclusion_running?() :: boolean()
Check to see if there is an inclusion process running
Start learn mode on the controller
@spec learn_mode_stop() :: :ok | status()
Stop learn mode on the controller
Start the process to remove a Z-Wave node from the network
@spec remove_node_stop() :: :ok | status()
Stop a remove node inclusion process
@spec set_input_dsk(Grizzly.ZWave.DSK.t()) :: :ok | status()
Tell the inclusion process what the input DSK is
If the NodeAddDSKReport
's :input_dsk_length
is 0
you can just call this
function without any arguments:
Grizzly.Inclusions.set_input_dsk()
If you are doing :s2_authenticated
or :s2_access_control
the
NodeAddDSKReport
will probably ask for input DSK length of 2
. This means
it is expecting a 2 byte (16 bit) number, which is normally a 5 digit pin
located somewhere on the node that is being added. After locating the pin and
you can pass it as an argument like so:
{:ok, dsk} = Grizzly.ZWave.DSK.parse("12345")
Grizzly.Inclusions.set_input_dsk(dsk)
@spec status() :: status()
Get the current status of the inclusion process
@spec stop() :: :ok
Stop the inclusion runner