Skip to content

Commit 9384c93

Browse files
committed
Revert removing the listening? node info property
It was removed on the basis of the Z-Wave documentation at "5.2.5.4.4. Node info cached report" describing the `List.` bit as ``` List (1 bit)The Optional Functionality bit indicates if true ( == '1') the node supports more command classes in addition to the ones covered by the device classes listed in this message. The additional command classes follow the device class fields. ``` The official documentation is wrong here. The `List` bit does indicate whether or not the device is "mains powered" and thus constantly listening. See "2.1.4.2. Application Specific Part" in the Z-Wave documentation for a description of the `listening` flag which value is the same as the `List.` bit in the Node Info Cached Report command.
1 parent 7682b25 commit 9384c93

File tree

11 files changed

+57
-24
lines changed

11 files changed

+57
-24
lines changed

lib/grizzly/virtual_devices/reports.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ defmodule Grizzly.VirtualDevices.Reports do
3030
seq_number: 0x00,
3131
node_id: device_entry.id,
3232
status: :done,
33+
listening?: true,
3334
basic_device_class: device_entry.device_class.basic_device_class,
3435
generic_device_class: device_entry.device_class.generic_device_class,
3536
specific_device_class: device_entry.device_class.specific_device_class,
@@ -77,6 +78,7 @@ defmodule Grizzly.VirtualDevices.Reports do
7778
seq_number: seq_number,
7879
status: :ok,
7980
age: 1,
81+
listening?: true,
8082
command_classes: command_classes_for_device(entry.device_class),
8183
basic_device_class: entry.device_class.basic_device_class,
8284
specific_device_class: entry.device_class.specific_device_class,

lib/grizzly/zwave/command_classes/network_management_inclusion.ex

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusion do
7575
7676
node information from a node add status report
7777
78+
* `:listening?` - is the device a listening device
7879
* `:basic_device_class` - the basic device class
7980
* `:generic_device_class` - the generic device class
8081
* `:specific_device_class` - the specific device class
@@ -89,6 +90,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusion do
8990
required(:seq_number) => byte(),
9091
required(:node_id) => Grizzly.ZWave.node_id(),
9192
required(:status) => node_add_status(),
93+
required(:listening?) => boolean(),
9294
required(:basic_device_class) => DeviceClasses.basic_device_class(),
9395
required(:generic_device_class) => DeviceClasses.generic_device_class(),
9496
required(:specific_device_class) => DeviceClasses.specific_device_class(),
@@ -103,6 +105,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusion do
103105
104106
Node information from an extended node add status report
105107
108+
* `:listening?` - is the device a listening device
106109
* `:basic_device_class` - the basic device class
107110
* `:generic_device_class` - the generic device class
108111
* `:specific_device_class` - the specific device class
@@ -111,6 +114,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusion do
111114
* `:kex_fail_type` - the type of key exchange failure if there is one
112115
"""
113116
@type extended_node_info_report() :: %{
117+
required(:listening?) => boolean(),
114118
required(:basic_device_class) => DeviceClasses.basic_device_class(),
115119
required(:generic_device_class) => DeviceClasses.generic_device_class(),
116120
required(:specific_device_class) => DeviceClasses.specific_device_class(),
@@ -124,7 +128,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusion do
124128
"""
125129
@spec parse_node_info(binary()) :: node_info_report() | extended_node_info_report()
126130
def parse_node_info(
127-
<<node_info_length, _extra_ccs?::1, _::7, _opt_func, basic_device_class,
131+
<<node_info_length, listening?::1, _::7, _opt_func, basic_device_class,
128132
generic_device_class, specific_device_class,
129133
command_classes::binary-size(node_info_length - 6), rest::binary>>
130134
) do
@@ -141,11 +145,12 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusion do
141145
specific_device_class
142146
)
143147

144-
# node info length includes: node_info_length, extra_ccs?, opt_func, basic class,
148+
# node info length includes: node_info_length, listening?, opt_func, basic class,
145149
# generic class, specific class, and the command class list. Granted keys, kex fail
146150
# type, and DSK are not included.
147151

148152
%{
153+
listening?: listening? == 1,
149154
basic_device_class: basic_device_class,
150155
generic_device_class: generic_device_class,
151156
specific_device_class: specific_device_class,

lib/grizzly/zwave/commands/extended_node_add_status.ex

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ defmodule Grizzly.ZWave.Commands.ExtendedNodeAddStatus do
1010
* `:seq_number` - the sequence number of the inclusion command
1111
* `:status` - the status of the inclusion
1212
* `:node_id` - the new id of the new Z-Wave node
13+
* `:listening?` - if the node is a listening node or not
1314
* `:basic_device_class` - the Z-Wave basic device class
1415
* `:generic_device_class` - the Z-Wave generic device class
1516
* `:specific_device_class` - the Z-Wave specific device class
@@ -34,6 +35,7 @@ defmodule Grizzly.ZWave.Commands.ExtendedNodeAddStatus do
3435
{:node_id, Grizzly.node_id()}
3536
| {:status, NetworkManagementInclusion.node_add_status()}
3637
| {:seq_number, Grizzly.seq_number()}
38+
| {:listening?, boolean()}
3739
| {:basic_device_class, byte()}
3840
| {:generic_device_class, byte()}
3941
| {:specific_device_class, byte()}
@@ -66,22 +68,22 @@ defmodule Grizzly.ZWave.Commands.ExtendedNodeAddStatus do
6668
if status == :failed do
6769
<<seq_number, status_byte, node_id::16, 0x01>>
6870
else
71+
listening? = Command.param!(command, :listening?)
6972
basic_device_class = Command.param!(command, :basic_device_class)
7073
generic_device_class = Command.param!(command, :generic_device_class)
7174
specific_device_class = Command.param!(command, :specific_device_class)
7275
command_classes = Command.param!(command, :command_classes)
73-
extra_ccs? = not Enum.empty?(command_classes)
7476

7577
# We add 6 to the length of the command classes to account for the 3 device
7678
# classes 2 Z-Wave protocol bytes and the node info length byte.
7779
# Also add the number of command classes plus 4 bytes for the separators
7880
# See SDS13784 4.4.8.2 for more details
7981
node_info_length = 6 + cc_count(command_classes)
8082

81-
extra_ccs_bit = if extra_ccs?, do: 1, else: 0
83+
listening_bit = if listening?, do: 1, else: 0
8284

83-
# TODO: fix opt func bit (after the extra_ccs bit)
84-
<<seq_number, status_byte, node_id::16, node_info_length, extra_ccs_bit::1, 0x00::7, 0x00,
85+
# TODO: fix opt func bit (after the listening bit)
86+
<<seq_number, status_byte, node_id::16, node_info_length, listening_bit::1, 0x00::7, 0x00,
8587
basic_device_class, generic_device_class,
8688
specific_device_class>> <>
8789
CommandClasses.command_class_list_to_binary(command_classes) <>
@@ -111,6 +113,7 @@ defmodule Grizzly.ZWave.Commands.ExtendedNodeAddStatus do
111113
status: NetworkManagementInclusion.parse_node_add_status(status_byte),
112114
seq_number: seq_number,
113115
node_id: node_id,
116+
listening?: false,
114117
basic_device_class: :unknown,
115118
generic_device_class: :unknown,
116119
specific_device_class: :unknown,

lib/grizzly/zwave/commands/node_add_status.ex

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ defmodule Grizzly.ZWave.Commands.NodeAddStatus do
99
* `:seq_number` - the sequence number of the inclusion command
1010
* `:status` - the status of the inclusion
1111
* `:node_id` - the new id of the new Z-Wave node
12+
* `:listening?` - if the node is a listening node or not
1213
* `:basic_device_class` - the Z-Wave basic device class
1314
* `:generic_device_class` - the Z-Wave generic device class
1415
* `:specific_device_class` - the Z-Wave specific device class
@@ -34,6 +35,7 @@ defmodule Grizzly.ZWave.Commands.NodeAddStatus do
3435
{:node_id, Grizzly.node_id() | Grizzly.VirtualDevices.id()}
3536
| {:status, NMI.node_add_status()}
3637
| {:seq_number, Grizzly.seq_number()}
38+
| {:listening?, boolean()}
3739
| {:basic_device_class, byte()}
3840
| {:generic_device_class, byte()}
3941
| {:specific_device_class, byte()}
@@ -66,22 +68,22 @@ defmodule Grizzly.ZWave.Commands.NodeAddStatus do
6668
if status == :failed do
6769
<<seq_number, NMI.node_add_status_to_byte(status), 0x00, node_id, 0x01>>
6870
else
69-
command_classes = Command.param(command, :command_classes, [])
70-
extra_ccs? = not Enum.empty?(command_classes)
71+
listening? = Command.param!(command, :listening?)
7172
basic_device_class = Command.param!(command, :basic_device_class)
7273
generic_device_class = Command.param!(command, :generic_device_class)
7374
specific_device_class = Command.param!(command, :specific_device_class)
75+
command_classes = Command.param(command, :command_classes, [])
7476

7577
# We add 6 to the length of the command classes to account for the 3 device
7678
# classes 2 Z-Wave protocol bytes and the node info length byte.
7779
# Also add the number of command classes plus 4 bytes for the separators
7880
# See SDS13784 4.4.8.2 for more details
7981
node_info_length = 6 + cc_count(command_classes)
8082

81-
# TODO: fix opt func bit (after the extra_ccs bit)
83+
# TODO: fix opt func bit (after the listening bit)
8284
binary =
8385
<<seq_number, NMI.node_add_status_to_byte(status), 0x00, node_id, node_info_length,
84-
encode_extra_ccs_bit(extra_ccs?)::size(1), 0x00::7, 0x00,
86+
encode_listening_bit(listening?)::size(1), 0x00::7, 0x00,
8587
DeviceClasses.basic_device_class_to_byte(basic_device_class),
8688
DeviceClasses.generic_device_class_to_byte(generic_device_class),
8789
DeviceClasses.specific_device_class_to_byte(generic_device_class, specific_device_class)>> <>
@@ -98,6 +100,7 @@ defmodule Grizzly.ZWave.Commands.NodeAddStatus do
98100
status: NMI.parse_node_add_status(status_byte),
99101
seq_number: seq_number,
100102
node_id: node_id,
103+
listening?: false,
101104
basic_device_class: :unknown,
102105
generic_device_class: :unknown,
103106
specific_device_class: :unknown,
@@ -120,9 +123,9 @@ defmodule Grizzly.ZWave.Commands.NodeAddStatus do
120123
{:ok, params}
121124
end
122125

123-
@spec encode_extra_ccs_bit(boolean()) :: byte()
124-
def encode_extra_ccs_bit(true), do: 0x01
125-
def encode_extra_ccs_bit(false), do: 0x00
126+
@spec encode_listening_bit(boolean()) :: byte()
127+
def encode_listening_bit(true), do: 0x01
128+
def encode_listening_bit(false), do: 0x00
126129

127130
defp maybe_add_version_2_fields(command, command_bin) do
128131
case Command.param(command, :granted_keys) do

lib/grizzly/zwave/commands/node_info_cached_report.ex

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ defmodule Grizzly.ZWave.Commands.NodeInfoCacheReport do
1111
- `:status` - the status fo the node information (required)
1212
- `:age` - the age of the cache data. A number that is expressed `2 ^ n`
1313
minutes (required)
14-
- `:command_classes` - a list of lists of command classes tagged by security attributes, in addition to those implied by the device classes (optional default empty
14+
- `:listening?` - if the node is listening node or sleeping node (required)
15+
- `:command_classes` - a list of lists of command classes tagged by security attributes (optional default empty
1516
list)
1617
- `:basic_device_class` - the basic device class (required)
1718
- `:generic_device_class` - the generic device class (required)
@@ -20,6 +21,7 @@ defmodule Grizzly.ZWave.Commands.NodeInfoCacheReport do
2021
@behaviour Grizzly.ZWave.Command
2122

2223
import Bitwise
24+
import Grizzly.ZWave.Encoding
2325

2426
alias Grizzly.ZWave.Command
2527
alias Grizzly.ZWave.CommandClasses.NetworkManagementProxy
@@ -46,6 +48,7 @@ defmodule Grizzly.ZWave.Commands.NodeInfoCacheReport do
4648
{:seq_number, Grizzly.seq_number()}
4749
| {:status, status()}
4850
| {:age, 1..14}
51+
| {:listening?, boolean()}
4952
| {:command_classes, [tagged_command_classes]}
5053
| {:basic_device_class, DeviceClasses.basic_device_class()}
5154
| {:generic_device_class, DeviceClasses.generic_device_class()}
@@ -71,8 +74,8 @@ defmodule Grizzly.ZWave.Commands.NodeInfoCacheReport do
7174
seq_number = Command.param!(command, :seq_number)
7275
status_byte = encode_status(Command.param!(command, :status))
7376
age = Command.param!(command, :age)
77+
listening_byte = encode_listening?(Command.param!(command, :listening?))
7478
command_classes = Command.param!(command, :command_classes)
75-
extra_ccs_byte = encode_extra_ccs(not Enum.empty?(command_classes))
7679

7780
basic_device_class_byte =
7881
DeviceClasses.basic_device_class_to_byte(Command.param!(command, :basic_device_class))
@@ -88,14 +91,14 @@ defmodule Grizzly.ZWave.Commands.NodeInfoCacheReport do
8891
optional_functionality_byte = encode_optional_functionality_byte(command_classes)
8992

9093
# the `0x00` byte is a reserved byte for Z-Wave and must be set to 0x00
91-
<<seq_number, status_byte ||| age, extra_ccs_byte, optional_functionality_byte, 0x00,
94+
<<seq_number, status_byte ||| age, listening_byte, optional_functionality_byte, 0x00,
9295
basic_device_class_byte, DeviceClasses.generic_device_class_to_byte(generic_device_class),
9396
specific_device_class_byte>> <> CommandClasses.command_class_list_to_binary(command_classes)
9497
end
9598

9699
@impl Grizzly.ZWave.Command
97100
def decode_params(
98-
<<seq_number, status::4, age::4, _extra_ccs?::1, _::7, _, _keys, basic_device_class_byte,
101+
<<seq_number, status::4, age::4, list?::1, _::7, _, _keys, basic_device_class_byte,
99102
generic_device_class_byte, specific_device_class_byte, command_classes::binary>>
100103
) do
101104
{:ok, basic_device_class} =
@@ -116,6 +119,7 @@ defmodule Grizzly.ZWave.Commands.NodeInfoCacheReport do
116119
basic_device_class: basic_device_class,
117120
generic_device_class: generic_device_class,
118121
specific_device_class: specific_device_class,
122+
listening?: bit_to_bool(list?),
119123
command_classes: CommandClasses.command_class_list_from_binary(command_classes),
120124
status: decode_status(status),
121125
age: age
@@ -125,8 +129,8 @@ defmodule Grizzly.ZWave.Commands.NodeInfoCacheReport do
125129
def encode_status(_), do: 0
126130
def encode_command_classes(_), do: 0
127131

128-
def encode_extra_ccs(true), do: 0x80
129-
def encode_extra_ccs(false), do: 0x00
132+
def encode_listening?(true), do: 0x80
133+
def encode_listening?(false), do: 0x00
130134

131135
def encode_optional_functionality_byte([]), do: 0x00
132136
def encode_optional_functionality_byte(_), do: 0x80

test/grizzly/zipgateway/ready_checker_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ defmodule Grizzly.ZIPGateway.ReadyCheckerTest do
3030
ready_checker = start_supervised!({ReadyChecker, [name: ctx.test, status_reporter: on_ready]})
3131

3232
send(ready_checker, @report)
33-
assert_receive :received_ready, 1_000
33+
assert_receive :received_ready
3434
end
3535

3636
test "exception in callback does not crash ReadyChecker", ctx do

test/grizzly/zwave/command_classes/network_management_inclusion_test.exs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusionTest do
3535
describe "parsing node information" do
3636
test "version 1 - only a list of command classes" do
3737
node_info_bin =
38-
<<0x10, 0x80, 0x00, 0x01, 0x02, 0x03, 0x20, 0x32, 0xEF, 0xF1, 0x00, 0x71, 0x25, 0xEF,
38+
<<0x10, 0x00, 0x00, 0x01, 0x02, 0x03, 0x20, 0x32, 0xEF, 0xF1, 0x00, 0x71, 0x25, 0xEF,
3939
0x62, 0x63>>
4040

4141
expected_command_classes = [
@@ -49,13 +49,14 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusionTest do
4949
command_classes: expected_command_classes,
5050
basic_device_class: :controller,
5151
generic_device_class: :static_controller,
52+
listening?: false,
5253
specific_device_class: :static_installer_tool
5354
}
5455
end
5556

5657
test "version 2 - adds S2 key values" do
5758
node_info_bin =
58-
<<0x10, 0x80, 0x00, 0x01, 0x02, 0x03, 0x20, 0x32, 0xEF, 0xF1, 0x00, 0x71, 0x25, 0xEF,
59+
<<0x10, 0x00, 0x00, 0x01, 0x02, 0x03, 0x20, 0x32, 0xEF, 0xF1, 0x00, 0x71, 0x25, 0xEF,
5960
0x62, 0x63, 0x07, 0x00>>
6061

6162
expected_command_classes = [
@@ -69,6 +70,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusionTest do
6970
command_classes: expected_command_classes,
7071
basic_device_class: :controller,
7172
generic_device_class: :static_controller,
73+
listening?: false,
7274
specific_device_class: :static_installer_tool,
7375
kex_fail_type: :none,
7476
granted_keys: [:s2_access_control, :s2_authenticated, :s2_unauthenticated]
@@ -77,7 +79,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusionTest do
7779

7880
test "version 3 - adds input DSK field - when DSK is empty" do
7981
node_info_bin =
80-
<<0x10, 0x80, 0x00, 0x01, 0x02, 0x03, 0x20, 0x32, 0xEF, 0xF1, 0x00, 0x71, 0x25, 0xEF,
82+
<<0x10, 0x00, 0x00, 0x01, 0x02, 0x03, 0x20, 0x32, 0xEF, 0xF1, 0x00, 0x71, 0x25, 0xEF,
8183
0x62, 0x63, 0x07, 0x00, 0x00>>
8284

8385
expected_command_classes = [
@@ -91,6 +93,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusionTest do
9193
command_classes: expected_command_classes,
9294
basic_device_class: :controller,
9395
generic_device_class: :static_controller,
96+
listening?: false,
9497
specific_device_class: :static_installer_tool,
9598
kex_fail_type: :none,
9699
granted_keys: [:s2_access_control, :s2_authenticated, :s2_unauthenticated]
@@ -99,7 +102,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusionTest do
99102

100103
test "version 3 - adds input DSK field - when DSK is provided" do
101104
node_info_bin =
102-
<<0x10, 0x80, 0x00, 0x01, 0x02, 0x03, 0x20, 0x32, 0xEF, 0xF1, 0x00, 0x71, 0x25, 0xEF,
105+
<<0x10, 0x00, 0x00, 0x01, 0x02, 0x03, 0x20, 0x32, 0xEF, 0xF1, 0x00, 0x71, 0x25, 0xEF,
103106
0x62, 0x63, 0x07, 0x00, 0x10, 0xC4, 0x6D, 0x49, 0x83, 0x26, 0xC4, 0x77, 0xE3, 0x3E,
104107
0x65, 0x83, 0xAF, 0xF, 0xA5, 0xE, 0x27>>
105108

@@ -116,6 +119,7 @@ defmodule Grizzly.ZWave.CommandClasses.NetworkManagementInclusionTest do
116119
command_classes: expected_command_classes,
117120
basic_device_class: :controller,
118121
generic_device_class: :static_controller,
122+
listening?: false,
119123
specific_device_class: :static_installer_tool,
120124
kex_fail_type: :none,
121125
granted_keys: [:s2_access_control, :s2_authenticated, :s2_unauthenticated],

test/grizzly/zwave/commands/extended_node_add_status_test.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ defmodule Grizzly.ZWave.Commands.ExtendedNodeAddStatusTest do
3535
command_classes: expected_command_classes,
3636
basic_device_class: :controller,
3737
generic_device_class: :static_controller,
38+
listening?: false,
3839
specific_device_class: :static_installer_tool,
3940
kex_fail_type: :none,
4041
granted_keys: [:s2_access_control, :s2_authenticated, :s2_unauthenticated]

test/grizzly/zwave/commands/node_add_status_test.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ defmodule Grizzly.ZWave.Commands.NodeAddStatusTest do
2525
command_classes: expected_command_classes,
2626
basic_device_class: :controller,
2727
generic_device_class: :static_controller,
28+
listening?: false,
2829
specific_device_class: :static_installer_tool
2930
]
3031

@@ -54,6 +55,7 @@ defmodule Grizzly.ZWave.Commands.NodeAddStatusTest do
5455
command_classes: expected_command_classes,
5556
basic_device_class: :controller,
5657
generic_device_class: :static_controller,
58+
listening?: false,
5759
specific_device_class: :static_installer_tool,
5860
kex_fail_type: :none,
5961
granted_keys: [:s2_access_control, :s2_authenticated, :s2_unauthenticated]
@@ -88,6 +90,7 @@ defmodule Grizzly.ZWave.Commands.NodeAddStatusTest do
8890
command_classes: expected_command_classes,
8991
basic_device_class: :controller,
9092
generic_device_class: :static_controller,
93+
listening?: false,
9194
specific_device_class: :static_installer_tool,
9295
kex_fail_type: :none,
9396
granted_keys: [:s2_access_control, :s2_authenticated, :s2_unauthenticated],
@@ -137,6 +140,7 @@ defmodule Grizzly.ZWave.Commands.NodeAddStatusTest do
137140
status: :failed,
138141
node_id: 7,
139142
seq_number: 37,
143+
listening?: false,
140144
basic_device_class: :routing_end_node,
141145
generic_device_class: :sensor_notification,
142146
specific_device_class: :notification_sensor,

0 commit comments

Comments
 (0)