Grizzly v0.9.0 is an almost complete rewrite of Grizzly. It has been a massive overhaul that started nearly 6 months go and I am very excited about this release. Over the years we have learned a lot Z-Wave, Elixir, and OTP and with this refactor we were able to build a more reliable, robust, and consistent solution.
{:grizzly, "~> 0.9.0-rc.0"}
By default, Grizzly will start and manage thezipgateway
binary automatically and once we have established a good connection to the Z-Wave controller we will let you know that Grizzly is ready to start handling Z-Wave commands. This mechanism is still part of Grizzly but we have changed the configuration of it.
You will no longer get a push from Grizzly when it is ready. Now, you can specify a module function args in the runtime config:
config :grizzly,
runtime: [
on_ready: {MyApp, :zwave_ready, []}
]
The configuration field for run_zipgaeway_bin
has been moved into the :runtime
configuration
config :grizzly,
runtime: [
run_zipgateway_bin: false
]
But this only useful if you don't want Grizzly supervising the zipgateway binary.
A bare minume working config now looks like:
config :grizzly,
runtime: [
on_ready: {MyApp, :a_function_my_app_module, []}
],
serail_port: <serial device>
See the Grizzly README for more information about configuration options.
The main function of Grizzly is Grizzly.send_command/3
. It took many different arguments and returned many different things. The send_comamnd
looks like this:
Grizzly.send_command(node_id, command :: atom(), command_args :: keyword(), command_opts :: keyword())
This function no longer takes a Grizzly.Node
as that structure was deleted. The first argument now is always a node id.
The second argument use to be a module, but now we have moved to use atoms and controlling more of the implementation details of each command. To see the commands we support and the parameters they take you can the Grizzly.ZWave.Commands
namespace.
The third argument says the same, just a keyword list of command parameters. This defaults to an empty keyword list.
The last argument is the command options. Most notably you can pass retires and timeouts in this field.
As a concrete example, let us assume I have a binary switch (on/off switch) on my network and is node id 3
:
iex> Grizzly.send_command(3, :switch_binary_get)
%Grizzly.ZWave.Command{...}
iex> Grizzly.send_command(3, :switch_binary_set, value: :on)
:ok
Now I can add some command options to send_command
iex> Grizzly.send_command(3, :switch_binary_get, [], retries: 5)
%Grizzly.ZWave.Command{...}
iex> Grizzly.send_command(3, :switch_binary_set, [value: :off], timeout: 1_000)
The return value was a map, but is now a Grizzly.ZWave.Command
data structure. This provides a more consistent return value while giving some dynamic nature for each command.
The command structure has a :pramas
field which is used to store the dynamic parameters for each command. This can be accessed via the Grizzly.ZWave.Command.param/2
or Grizzly.ZWave.Command.param!/2
functions.
iex> return_command = Grizzly.send_command(3, :switch_binary_get)
iex> return_command
%Grizzly.ZWave.Command{
...
params: [value: :off],
...
}
iex> Grizzly.ZWave.Command.param!(return_command, :value)
:on
iex> Grizzly.ZWave.Command.param(return_command, :not_there)
nil
The functions:
Grizzly.add_node
Grizzly.remove_node
Grizzly.add_node_stop
Grizzly.remove_node_stop
Have all moved to Grizzly.Inclusions
module, so you can update like so:
alias Grizzly.Inclusions
...
Inclusions.add_node
...
The messages you receive from an inclusion now follow this pattern:
{:grizzly, :inclusion, %Grizzly.ZWave.Command{}}
We also don't automatically assign associations during inclusion anymore as not all applications desire for that to happen the way we dictate and we have opted to give the consumer more flexibility on how that should work. If you still want to get your devices talking to your hub after inclusion is complete you can call the new function: Grizzly.Node.set_lifeline_association
.
For more information on some new features around inclusions see Grizzly.Inclusuions
module docs.
Grizzly.Node
structGrizzly.Conn
moduleGrizzly.Notifications
moduleGrizzly.Packet
moduleGrizzly.close_connection
Grizzly.command_class_versions_known?
Grizzly.update_command_class_versions
Grizzly.start_learn_mode
Grizzly.get_command_class_version
Grizzly.has_command_class
Grizzly.connected?
Grizzly.has_command_class_names
Grizzly.config
Grizzly.Network.busy?
Grizzly.Network.ready?
Grizzly.Network.get_state
Grizzly.Network.set_state
Grizzly.Network.get_node
Grizzly.Node.new
Grizzly.Node.update
Grizzly.Node.put_ip
Grizzly.Node.get_ip
Grizzly.Node.connect
Grizzly.Node.disconnect
Grizzly.Node.make_config
Grizzly.Node.has_command_class?
Grizzly.Node.connected?
Grizzly.Node.command_class_names
Grizzly.Node.update_command_class_versions
Grizzly.Node.get_command_class_version
Grizzly.Node.command_class_version_known?
Grizzly.Node.update_command_class
Grizzly.Node.put_association
Grizzly.Node.get_association_list
Grizzly.Node.configure_association
Grizzly.Node.get_network_information
Grizzly.Node.initialize_command_versions
Grizzly.reset_controller
->Grizzly.Network.reset_controller
Grizzly.get_nodes
->Grizzly.Network.get_node_ids
Grizzly.get_node_info
->Grizzly.Node.get_node_info
Grizzly.Notifications.subscribe
->Grizzly.subscribe_command
andGrizzly.subscribe_commands
Grizzly.Notifications.unsubscribe
->Grizzly.unsubscribe
Grizzly.add_node
->Grizzly.Inclusions.add_node
Grizzly.remove_node
->Grizzly.Inclusions.remove_node
Grizzly.add_node_stop
->Grizzly.Inclusions.add_node_stop
Grizzly.remove_node_stop
->Grizzly.Inclusions.remove_node_stop
Grizzly.Client
->Grizzly.Transport
Grizzly.Security
->Grizzly.ZWave.Security
Grizzly.DSK
->Grizzly.ZWave.DSK
Grizzly.Node.add_lifeline_group
->Grizzly.Node.set_lifeline_association
All the commands that removed can be handled via send_command
directly or using Elixir standard library functions.
The node data structure is removed, and updating anywhere you pattern match %Grizzly.Node{}
will have to be updated. If you trying to do something particular with a node you can use send_command
with the node id to accomplish that.
We removed Grizzly.Notifications
and provide there functions for working with getting events from the Z-Wave network:
Grizzly.subscribe_command/1
Grizzly.subscribe_commands/1
Grizzly.unsubscribe_command/1
The notifications of Grizzly < 0.9.0 used a custom notification topic, but 0.9.0 and greater you subscribe to a command or commands.
Old:
Grizzly.subscribe(:unsolicated_message)
This would just dump all messages from Z-Wave to the process that is listening for the incoming messages. However, we learned that often times processes just are wanting a few commands and the rest are greatly ignored.
Update to:
Grizzly.subscribe_command(:switch_binary_report)
Then when you handle the message you should expect this pattern:
{:grizzly, :event, <node_id>, %Grizzly.Command{...}}