Skip to content

Instantly share code, notes, and snippets.

@mattludwigs
Last active August 10, 2020 17:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattludwigs/323cbdbfc32075745cd3fdae7163c930 to your computer and use it in GitHub Desktop.
Save mattludwigs/323cbdbfc32075745cd3fdae7163c930 to your computer and use it in GitHub Desktop.
Grizzly v0.12 -> v0.13

Send a Command get a Report

The major breaking change to Grizzly when going from v0.12 or earlier to v0.13 is the main API call Grizzly.send_command/4 now returns {:ok, %Grizzly.Report{}} when the command was successfully sent. A successful command can return 4 primary reports:

  • :ack_response
  • :command
  • :queued
  • :timeout

This types can be accessed in the Grizzly.Report's :type field.

When using send_command/4 the old code would look like:

case Grizzly.send_command(node_id, command, command_args, command_opts) do
  :ok -> # do stuff
  {:ok, %Grizzly.Command{}} -> # do stuff
  {:queued, ref, delay_seconds} -> # do stuff
end

To update the above code:

case Grizzly.send_command(node_id, command, command_args, command_opts) do
  {:ok, %Grizzly.Report{status: :complete, type: :ack_response}} -> # do stuff
  {:ok, %Grizzly.Report{status: :complete, type: :command}} -> # do stuff
  {:ok, %Grizzly.Report{status: :complete, type: :timeout}} -> # do stuff
  {:ok, %Grizzly.Report{status: :inflight, type: :queued}} -> # do stuff
end

Notice the queued command's status is considered to still be inflight as it hasn't reached the destination node yet.

A :complete report means the command finished its lifecylce and no runtime issues with processing the command and the responses to the command.

When you have a :command type of report you can access the Z-wave command via the :command field of the report.

If the command is queued and you want to track the life of the queued command the reference to the command is in the :command_ref field of the report. Also, to know how long the command is projected to delayed you can use the :queued_delay field of the report, this is in seconds.

For more information about the new report data structure please see the Grizzly.Report module docs.

Handling Queued Reports

Just like the <= v0.12 versions when a command is queued there are ping and a final reports. This was sent to the calling process in this form:

{:grizzly, :queued_command_response, %Grizzly.Command{}}

{:grizzly, :queued_ping, reference, remaining_delay}

To handle the new report based messaging with queued commands you should update to handle:

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

An example of this might look like:

def handle_info({:grizzly, :report, report}, state) do
  if report.queued do
    handle_queued_response(report, state)
  else
    handle_unknown_report(report, state)
  end
end

def handle_queued_response(report, state) do
  case report do
    %Report{status: :inflight, type: :queued_ping} ->
      # and updated queued delay timer can be found in the
      # queued_delay field of the report like: report.queued_delay
    %Report{status: :complete, type: :ack_response} ->
      # do stuff with the ack response report
    %Report{status: :complete, type: :command} ->
      # do something with the command that can be found in the
      # report's :command field like: report.command
    %Report{status: :complete, type: :timeout} ->
      # when the device woke up and the controller sent the
      # command, for some reason the command timedout.
  end
end

Inclusions

The Grizzly inclusion handler behaviour has changed from handle_command/2 to handle_report/2 and the inclusion handler will be sent the report data stucuture.

Unsolicited Messages

Unsolicited messages are messages from the Z-Wave network to Grizzly. This might be montion detected report or an unlock report if a lock was manually unlocked. When subscribiing to a command to listen to the old message that was sent use to be:

{:grizzly, :event, %Grizzly.Command{}

This is now

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

Where the Grizzly.Command data structure can be accessed by the :command field on the report.

Pushed Reports

The patterns for handling vairous pushed messages looked like:

# queued command reponse
{:grizzly, :queued_command_response, %Grizzly.Command{}}

# queued ping
{:grizzly, :queued_ping, reference, remaining_delay}

# unsolicited messages
{:grizzly, :event, %Grizzly.Command{}}

# inclusions
{:grizzly, :inclusion, %Grizzly.Command{}}

# firmware updates
{:grizzly, :firmware_update, %Grizzly.Command{}}

They all follow this pattern now:

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

Now that the Grizzly.Report data structure can provide a lot more context of the Z-Wave communication the handler of these messages can use pattern matching or other means to introspect the report to know how to handle it. This also makes the footprint of Grizzly's API a little smaller, hopefully lowering the learning curve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment