Packages
grizzly
0.7.0
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/command_class/network_management_inclusion/node_add.ex
defmodule Grizzly.CommandClass.NetworkManagementInclusion.NodeAdd do
@moduledoc """
Module for using the NODE_ADD command.
If the inclusion process is for S0 or no security the process will
add the node and do the security (if S0) exchange at the `zipgateway`
level.
If the inclusin process is for S2 security, there will be a
node add keys report, which is to request granting what level
of S2 security the user ought to grant. This request will let
the caller know if Client Side Authentication is request and what
S2 keys to grant to the joining node.
"""
@behaviour Grizzly.Command
alias Grizzly.{Node, Packet, Security}
alias Grizzly.Network.State, as: NetworkState
alias Grizzly.Command.{EncodeError, Encoding}
alias Grizzly.CommandClass.NetworkManagementInclusion
@typedoc """
Mode for the controller to use during inclsion
- `:any` - add any type of node to the network and allow for S0 bootstrapping
- `:stop` - stop add mode
- `:any_s2` - same as `:any`, but allow for S2 bootstrapping as well (v2)
"""
@type t :: %__MODULE__{
seq_number: Grizzly.seq_number(),
tx_opts: byte,
mode: NetworkManagementInclusion.add_mode() | byte,
pre_states: [NetworkState.state()],
exec_state: NetworkState.state(),
timeout: non_neg_integer
}
defstruct mode: :any_s2,
tx_opts: 0x20,
seq_number: nil,
pre_states: nil,
exec_state: nil,
timeout: nil
def init(opts) do
{:ok, struct(__MODULE__, opts)}
end
@spec encode(t) :: {:ok, binary} | {:error, EncodeError.t()}
def encode(%__MODULE__{seq_number: seq_number, tx_opts: tx_opts} = command) do
with {:ok, encoded} <-
Encoding.encode_and_validate_args(command, %{
mode: {:encode_with, NetworkManagementInclusion, :encode_add_mode}
}) do
binary =
Packet.header(seq_number) <> <<0x34, 0x01, seq_number, 0x00, encoded.mode, tx_opts>>
{:ok, binary}
end
end
@spec handle_response(t, Packet.t()) ::
{:continue, t}
| {:done, {:error, :nack_response}}
| {:done, Node.t()}
| {:done, {:ok, :node_add_stopped}}
def handle_response(
%__MODULE__{seq_number: seq_number, mode: :stop},
%Packet{
seq_number: seq_number,
types: [:ack_response]
}
) do
{:done, {:ok, :node_add_stopped}}
end
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},
%Packet{
seq_number: seq_number,
types: [:nack_response]
}
) do
{:done, {:error, :nack_response}}
end
def handle_response(
%__MODULE__{seq_number: seq_number},
%Packet{
seq_number: seq_number,
body: %{
command: :node_add_status,
status: :failed
}
}
) do
{:done, {:error, :node_add_failed}}
end
def handle_response(_, %Packet{body: %{command: :node_add_status, status: status} = report})
when status in [:done, :security_failed] do
zw_node =
Node.new(
id: report.node_id,
command_classes: report.command_classes,
security: security_from_report(status, report.keys_granted),
basic_cmd_class: report.basic_class,
generic_cmd_class: report.generic_class,
specific_cmd_class: report.specific_class,
listening?: report.listening?
)
{:done, {:ok, zw_node}}
end
def handle_response(
command,
%Packet{
body: %{
command: :node_add_keys_report,
csa?: csa?,
requested_keys: requested_keys
}
}
) do
{
:send_message,
{:node_add_keys_report, %{csa?: csa?, requested_keys: requested_keys}},
command
}
end
def handle_response(command, _), do: {:continue, command}
defp security_from_report(:security_failed, _), do: :failed
defp security_from_report(:done, keys_granted) do
Security.get_highest_level(keys_granted)
end
end