View Source Grizzly.Report (grizzly v8.5.3)
Reports from Z-Wave commands
When you send a command in Z-Wave you will receive a report back.
When Things Go Well
There are two primary reports that are returned when sending a command.
The first is :command
report and the second is an :ack_response
report.
These both will have a status of :complete
.
Normally, an :ack_response
report is returned when you set a value on a
device. This means the device received the command and is processing it,
not that the device has already processed it. You might have to go read the
value back after setting it if you want to make the device ran the set
based command.
A :command
report type is returned often after reading a value from a
device. This report will have its :command
field filled with a Z-Wave
command.
case Grizzly.send_command(node_id, command, command_args, command_opts) do
{:ok, %Grizzly.Report{status: :complete, type: :command} = report} ->
# do something withe report.command
{:ok, %Grizzly.Report{status: :complete, type: :ack_response}} ->
# do whatever
end
Queued Commands
When sending a command to a device that sleeping, normally battery powered
devices, the command will be queued internally. The command will still be
considered :inflight
as it has not reached the device yet. You know when
a command has been queued when the report's :status
field is :inflight
and the :type
field is :queued_delayed
. Fields to help you manage queued
commands are :command_ref
, :queued_delay
, and :node_id
During the command's queued lifetime the system sends pings back to the caller to ensure that the low level connection is still established. This also provides an updated delayed time before the device wakes up.
case Grizzly.send_command(node_id, command, command_args, command_opts) do
{:ok, %Grizzly.Report{status: :inflight, type: :queued_delay}} ->
# the command was just queued
end
Once the command has been queued the calling process will receive messages about the queued command like so:
{:grizzly, :report, %Report{}}
This report can take two forms. One for a completed queued command and one for a queued ping.
def handle_info({:grizzly, :report, report}, state) do
case report do
%Grizzly.Report{status: :inflight, type: :queued_ping} ->
# handle the ping if you want
# an updated queue delay will be found in the :queued_delay
# field of the report
%Grizzly.Report{status: :complete, type: :command, queued: true} ->
# here if the :queued field is marked has true and the report is
# complete that will indicate a command has made it to the sleeping
# device and the device has received the command
%Grizzly.Report{status: :complete, type: :timeout, queued: true} ->
# The woke up and the controller sent the command but for reason
# the command's processing timed out
end
end
Timeouts
If sending the command times out you will get a command with the :type
of
:timeout
case Grizzly.send_command(node_id, command, command_args, command_opts) do
{:ok, %Grizzly.Report{status: :complete, type: :timeout}} ->
# handle the timeout
end
The reason why this is considered okay is because the command that was sent was valid and we were able to establish a connect to the desired device but it just did not provide any report back.
Full Example
The below example shows the various ways one might match after calling
Grizzly.send_command/4
.
case Grizzly.send_command(node_id, command, command_args, command_opts) do
{:ok, %Grizzly.Report{status: :complete, type: :command} = report} ->
handle_complete_report(report)
{:ok, %Grizzly.Report{status: :complete, type: :ack_response} = report} ->
handle_complete_report(report)
{:ok, %Grizzly.Report{status: :complete, type: :timeout} = report} ->
handle_timeout(report)
{:ok, %Grizzly.Report{status: :inflight, type: :queued} = report} ->
handle_queued_command(report)
end
note: the handle_*
functions will need to implemented and are only used in
the example for illustration purposes
Summary
Types
The RSSI value between each device that command had to route through to get to the destination node
All the data for the status and type of a report.
The various transmission stats that are provide by the Z-Wave network when sending a command.
Types
@type opt() :: {:transmission_stats, [transmission_stat()]} | {:queued_delay, non_neg_integer()} | {:command, Grizzly.ZWave.Command.t()} | {:command_ref, reference()} | {:queued, boolean()} | {:acknowledged, boolean()}
@type rssi_value() :: integer() | :not_available
The RSSI value between each device that command had to route through to get to the destination node
If the value is :not_available
that means data for that hop in not available
or a hope did not take place. To see the nodes that the command was routed
through see the :last_working_route
field of the transmission stats.
@type status() :: :inflight | :complete
@type t() :: %Grizzly.Report{ acknowledged: boolean(), command: Grizzly.ZWave.Command.t() | nil, command_ref: reference() | nil, node_id: Grizzly.ZWave.node_id() | Grizzly.VirtualDevices.id(), queued: boolean(), queued_delay: non_neg_integer(), status: status(), transmission_stats: [transmission_stat()], type: type() }
All the data for the status and type of a report.
Fields
:status
- this indicates if the report is complete, inflight, or timed out:type
- this indicates if the report is contains a command or information about being queued.:command
- if the status is:complete
and the type is:command
then this field will contain a Z-Wave command in the report.:transmission_stats
- provides transmission stats for the command that was sent:queued_delay
- the delay time remaining if the report type is:queued_delay
or:queued_ping
:command_ref
- a reference to the command. This is mostly useful for tracking queued commands:node_id
- the node the report is responding from:queued
- this flag marks if the command was ever queued before completing:acknowledged
- whether the destination node acknowledged the command. Only valid when the status is:complete
. For commands using theAckResponse
command handler, this field will be true iftype
is:ack_response
and false iftype
is:nack_response
. For other command handlers, it will be true if the original command was acknowledged by the destination node (i.e. we received an ACK Response from Z/IP Gateway). This is useful for differentiating report timeouts where the destination received the command but didn't send a report (e.g. it doesn't support the command or command version, it considered some or all of the payload invalid, etc.) from other causes. Other types of timeouts typically mean the timeout was too short and Grizzly had to return before Z/IP Gateway could send a response
@type transmission_stat() :: {:transmit_channel, non_neg_integer()} | {:ack_channel, non_neg_integer()} | {:rssi_hops, [rssi_value()]} | {:rssi_4bars, 0..4 | :unknown} | {:rssi_dbm, rssi_value()} | {:last_working_route, [Grizzly.ZWave.node_id()]} | {:transmit_speed, transmit_speed()} | {:transmission_time, non_neg_integer()} | {:route_changed, boolean()}
The various transmission stats that are provide by the Z-Wave network when sending a command.
:transmit_channel
- the RF channel the command was transmitted on:ack_channel
- the RF channel the acknowledgement report was transmitted on:rssi
- a 5 tuple that contains RSSI values for each hop in the Z-Wave network:last_working_route
- this contains a 4 tuple that shows what nodes the Z-Wave command was routed through to the destination node. Also this contains the speed by which the Z-Wave command was transmitted to the destination:transmission_time
- the length of time until the reception of an acknowledgement in milliseconds:route_changed
- this indicates if the route was changed for the current transmission
@type transmit_speed() :: float() | non_neg_integer()
@type type() ::
:ack_response
| :nack_response
| :queue_full
| :command
| :queued_ping
| :unsolicited
| :queued_delay
| :timeout
| :supervision_status
Functions
@spec new(status(), type(), Grizzly.ZWave.node_id() | Grizzly.VirtualDevices.id(), [ opt() ]) :: t()
Make a new Grizzly.Report