Packages
grizzly
0.6.4
9.1.4
9.1.2
9.1.1
9.1.0
9.0.0
8.15.3
8.15.2
8.15.1
8.15.0
8.14.0
8.13.0
8.12.0
8.11.3
8.11.2
8.11.1
8.11.0
8.10.0
8.9.0
8.8.1
8.8.0
8.7.1
8.7.0
8.6.12
8.6.11
8.6.10
8.6.9
8.6.8
8.6.7
retired
8.6.6
8.6.5
8.6.4
8.6.3
8.6.2
8.6.1
8.6.0
8.5.3
8.5.2
8.5.1
8.5.0
8.4.0
8.3.0
8.2.3
8.2.2
8.2.1
8.2.0
8.1.0
8.0.1
8.0.0
7.4.3
7.4.2
7.4.1
7.4.0
7.3.0
7.2.0
7.1.4
7.1.3
7.1.2
7.1.1
7.1.0
7.0.4
7.0.3
7.0.2
7.0.1
7.0.0
6.8.8
6.8.7
6.8.6
6.8.5
6.8.4
6.8.3
6.8.2
6.8.1
6.8.0
6.7.1
6.7.0
6.6.1
6.6.0
6.5.1
6.5.0
6.4.0
6.3.0
6.2.0
6.1.1
6.1.0
6.0.1
6.0.0
5.4.1
5.4.0
5.3.0
5.2.8
5.2.7
5.2.6
5.2.5
5.2.4
5.2.3
5.2.2
5.2.1
5.2.0
5.1.2
5.1.1
5.1.0
5.0.2
5.0.1
5.0.0
4.0.1
4.0.0
3.0.0
2.1.0
2.0.0
1.0.1
1.0.0
0.22.7
0.22.6
0.22.5
0.22.4
0.22.3
0.22.2
0.22.1
0.22.0
0.21.1
0.21.0
0.20.2
0.20.1
0.20.0
0.19.1
0.19.0
0.18.3
0.18.2
0.18.1
0.18.0
0.17.7
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.2
0.16.1
0.16.0
0.15.11
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.9.0-rc.4
0.9.0-rc.3
0.9.0-rc.2
0.9.0-rc.1
0.9.0-rc.0
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.4.3
0.4.2
Elixir Z-Wave library
Current section
Files
Jump to
Current section
Files
lib/grizzly/packet/decode.ex
defmodule Grizzly.Packet.Decode do
@moduledoc false
import Bitwise
alias Grizzly.CommandClass.Mappings
alias Grizzly.Packet.HeaderExtension
require Logger
@packet_types %{
nack_option_error: 0x04,
nack_queue_full: 0x08,
nack_waiting: 0x10,
nack_response: 0x20,
ack_response: 0x40,
ack_request: 0x80
}
@doc """
Unmask the byte for which reponse types are in teh response type byte
"""
@spec get_packet_types(binary) :: [atom]
def get_packet_types(<<_command_data::binary-size(2), packet_types, _rest::binary>>) do
@packet_types
|> Enum.reduce([], fn {type, byte}, types ->
if (packet_types &&& byte) == byte do
types ++ [type]
else
types
end
end)
end
@doc """
Get the main Z-Wave body part of the packet
"""
@spec get_body(<<_::64>>) :: binary
def get_body(binary) do
header_extension_length = get_header_extension_length(binary)
<<_header_data::binary-size(7), _extensions::binary-size(header_extension_length),
body::binary>> = binary
_ =
Logger.debug(
"BODY of #{inspect(binary)} is #{inspect(body)}, header extension length is #{
header_extension_length
}"
)
body
end
def get_header_extensions(<<_::binary-size(7)>>), do: []
def get_header_extensions(<<_::binary-size(7), extension_length, rest::binary>>) do
length = extension_length - 1
<<extensions::binary-size(length), _::binary>> = rest
HeaderExtension.from_binary(extensions)
end
@doc """
Get the length of the header extension
"""
def get_header_extension_length(<<_header_data::binary-size(7)>>), do: 0
def get_header_extension_length(
<<_header_data::binary-size(7), extension_length, _rest::binary>>
),
do: extension_length
@doc """
Get the sequenece number from the packet
"""
@spec get_sequence_number(<<_::64>>) :: byte()
def get_sequence_number(bytestring) do
# Pay the cost of reparsing body now even if we have
# parsed it else where in the code. Maybe one day, if performance
# is an issue we can optimize this a bit more.
body = get_body(bytestring)
if network_management_command_class?(body) do
get_network_management_sequence_number(body)
else
get_zip_packet_sequence_number(bytestring)
end
end
def get_zip_packet_sequence_number(<<_frame_data::binary-size(4), seq_no, _rest::binary>>),
do: seq_no
def get_network_management_sequence_number(
<<_command_class_command::binary-size(2), seq_no, _rest::binary>>
),
do: seq_no
@doc """
Check the body/z-wave command class to see if it is network management
"""
def network_management_command_class?(<<0x52, _rest::binary>>), do: true
def network_management_command_class?(<<0x34, _rest::binary>>), do: true
def network_management_command_class?(_), do: false
@spec raw(<<_::16>>) :: map()
def raw(<<command_class>>), do: %{command_class: Mappings.from_byte(command_class)}
def raw(<<0x58, 0x01, _, node_id, ip::binary-size(16), home_id::binary>>) do
%{
command_class: :zip_nd,
command: :zip_node_advertisement,
ip_address: ip_bin_to_tuple(ip),
home_id: home_id,
node_id: node_id
}
end
def raw(<<0x58, 0x04, _, node_id>>) do
%{
command_class: :zip_nd,
command: :inv_node_solicitation,
node_id: node_id
}
end
defp ip_bin_to_tuple(
<<n1::size(16), n2::size(16), n3::size(16), n4::size(16), n5::size(16), n6::size(16),
n7::size(16), n8::size(16)>>
) do
{n1, n2, n3, n4, n5, n6, n7, n8}
end
end