-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for the Version get command (v2) to help get more information about Z-Wave firmware and protocol versions.
- Loading branch information
1 parent
47f3762
commit 5dc35a2
Showing
8 changed files
with
329 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
defmodule Grizzly.CommandClass.Version.Get do | ||
@moduledoc """ | ||
Module for working with the `VERSION GET` command. | ||
This is for getting version information about the module Z-Wave | ||
Command Options: | ||
* `:seq_number` - the sequence number used by the Z/IP packet | ||
* `:retries` - the number of attempts to send the command (default 2) | ||
""" | ||
|
||
@behaviour Grizzly.Command | ||
|
||
alias Grizzly.Packet | ||
alias Grizzly.CommandClass.Version | ||
|
||
@type t :: %__MODULE__{ | ||
seq_number: Grizzly.seq_number(), | ||
retries: non_neg_integer() | ||
} | ||
|
||
@type opt :: | ||
{:seq_number, Grizzly.seq_number()} | ||
| {:retries, non_neg_integer()} | ||
|
||
defstruct seq_number: nil, retries: 2 | ||
|
||
@spec init([opt]) :: {:ok, t} | ||
def init(opts) do | ||
{:ok, struct(__MODULE__, opts)} | ||
end | ||
|
||
@spec encode(t) :: {:ok, binary} | ||
def encode(%__MODULE__{seq_number: seq_number}) do | ||
{:ok, Packet.header(seq_number) <> <<0x86, 0x11>>} | ||
end | ||
|
||
@spec handle_response(t, Packet.t()) :: | ||
{:continue, t} | ||
| {:done, {:error, :nack_response}} | ||
| {:done, {:ok, Version.version_report()}} | ||
| {:retry, t} | ||
def handle_response(%__MODULE__{seq_number: seq_number} = command, %Packet{ | ||
seq_number: seq_number, | ||
types: [:ack_response] | ||
}) do | ||
{:continue, command} | ||
end | ||
|
||
def handle_response(%__MODULE__{seq_number: seq_number, retries: 0}, %Packet{ | ||
seq_number: seq_number, | ||
types: [:nack_response] | ||
}) do | ||
{:done, {:error, :nack_response}} | ||
end | ||
|
||
def handle_response(%__MODULE__{seq_number: seq_number, retries: n} = command, %Packet{ | ||
seq_number: seq_number, | ||
types: [:nack_response] | ||
}) do | ||
{:retry, %{command | retries: n - 1}} | ||
end | ||
|
||
def handle_response(_command, %Packet{ | ||
body: | ||
%{ | ||
command_class: Version, | ||
command: :version_report | ||
} = body | ||
}) do | ||
{:done, {:ok, Map.drop(body, [:command_class, :command])}} | ||
end | ||
|
||
def handle_response( | ||
%__MODULE__{seq_number: seq_number} = command, | ||
%Packet{ | ||
seq_number: seq_number, | ||
types: [:nack_response, :nack_waiting] | ||
} = packet | ||
) do | ||
if Packet.sleeping_delay?(packet) do | ||
{:queued, command} | ||
else | ||
{:continue, command} | ||
end | ||
end | ||
|
||
def handle_response(command, _), do: {:continue, command} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
defmodule Grizzly.CommandClass.Version.GetTest do | ||
use ExUnit.Case, async: true | ||
|
||
alias Grizzly.Packet | ||
alias Grizzly.CommandClass.Version | ||
alias Grizzly.CommandClass.Version.Get | ||
|
||
describe "implements Grizzly.Command behaviour" do | ||
test "initializes command state" do | ||
assert {:ok, %Get{}} = Get.init([]) | ||
end | ||
|
||
test "encodes correctly" do | ||
{:ok, command} = Get.init(seq_number: 0x05, command_class: :switch_binary) | ||
|
||
binary = <<35, 2, 128, 208, 5, 0, 0, 3, 2, 0, 0x86, 0x11>> | ||
|
||
assert {:ok, binary} == Get.encode(command) | ||
end | ||
|
||
test "handles ack response" do | ||
{:ok, command} = Get.init(seq_number: 0x05) | ||
packet = Packet.new(seq_number: 0x05, types: [:ack_response]) | ||
|
||
assert {:continue, ^command} = Get.handle_response(command, packet) | ||
end | ||
|
||
test "handles nack response" do | ||
{:ok, command} = Get.init(seq_number: 0x05, retries: 0) | ||
|
||
packet = Packet.new(seq_number: 0x05, types: [:nack_response]) | ||
assert {:done, {:error, :nack_response}} == Get.handle_response(command, packet) | ||
end | ||
|
||
test "handles retries" do | ||
{:ok, command} = Get.init(seq_number: 0x05) | ||
packet = Packet.new(seq_number: 0x05, types: [:nack_response]) | ||
|
||
assert {:retry, %Get{retries: 1}} = Get.handle_response(command, packet) | ||
end | ||
|
||
test "handles command class version report response" do | ||
report = %{ | ||
command_class: Version, | ||
command: :version_report, | ||
protocol_library: :controller, | ||
protocol_version: 1, | ||
protocol_sub_version: 1, | ||
firmware_version: 1, | ||
firmware_sub_version: 1 | ||
} | ||
|
||
packet = Packet.new(body: report) | ||
{:ok, command} = Get.init(seq_number: 0x05) | ||
|
||
assert {:done, {:ok, Map.drop(report, [:command_class, :command])}} == | ||
Get.handle_response(command, packet) | ||
end | ||
|
||
test "handles queued for wake up nodes" do | ||
{:ok, command} = Get.init(seq_number: 0x01, command_class: :switch_binary) | ||
|
||
packet = | ||
Packet.new(seq_number: 0x01, types: [:nack_response, :nack_waiting]) | ||
|> Packet.put_expected_delay(5000) | ||
|
||
assert {:queued, ^command} = Get.handle_response(command, packet) | ||
end | ||
|
||
test "handles nack waiting when delay is 1 or less" do | ||
{:ok, command} = Get.init(seq_number: 0x01) | ||
|
||
packet = | ||
Packet.new(seq_number: 0x01, types: [:nack_response, :nack_waiting]) | ||
|> Packet.put_expected_delay(1) | ||
|
||
assert {:continue, ^command} = Get.handle_response(command, packet) | ||
end | ||
|
||
test "handles other response" do | ||
{:ok, command} = Get.init(seq_number: 0x05) | ||
|
||
assert {:continue, ^command} = Get.handle_response(command, %{command: :ice_cream}) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
defmodule Grizzly.CommandClass.Version.Test do | ||
use ExUnit.Case, async: true | ||
|
||
alias Grizzly.CommandClass.Version | ||
|
||
describe "decoding library types" do | ||
test "static controller" do | ||
assert {:ok, :static_controller} == Version.decode_library_type(0x01) | ||
end | ||
|
||
test "controller" do | ||
assert {:ok, :controller} == Version.decode_library_type(0x02) | ||
end | ||
|
||
test "enhanced slave" do | ||
assert {:ok, :enhanced_slave} == Version.decode_library_type(0x03) | ||
end | ||
|
||
test "slave" do | ||
assert {:ok, :slave} == Version.decode_library_type(0x04) | ||
end | ||
|
||
test "installer" do | ||
assert {:ok, :installer} == Version.decode_library_type(0x05) | ||
end | ||
|
||
test "routing slave" do | ||
assert {:ok, :routing_slave} == Version.decode_library_type(0x06) | ||
end | ||
|
||
test "bridge controller" do | ||
assert {:ok, :bridge_controller} == Version.decode_library_type(0x07) | ||
end | ||
|
||
test "device under test" do | ||
assert {:ok, :device_under_test} == Version.decode_library_type(0x08) | ||
end | ||
|
||
test "av remote" do | ||
assert {:ok, :av_remote} == Version.decode_library_type(0x0A) | ||
end | ||
|
||
test "av device" do | ||
assert {:ok, :av_device} == Version.decode_library_type(0x0B) | ||
end | ||
|
||
test "invalid library type" do | ||
assert {:error, :invalid_library_type, 0xCC} == Version.decode_library_type(0xCC) | ||
end | ||
end | ||
|
||
test "decoding the version report" do | ||
report = %{ | ||
protocol_library: :controller, | ||
protocol_version: 1, | ||
protocol_sub_version: 1, | ||
firmware_version: 1, | ||
firmware_sub_version: 1 | ||
} | ||
|
||
assert {:ok, report} == Version.decode_version_report(<<0x02, 0x01, 0x01, 0x01, 0x01>>) | ||
end | ||
end |
Oops, something went wrong.