Packages
grizzly
8.8.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/trace/record.ex
defmodule Grizzly.Trace.Record do
@moduledoc """
Data structure for a single item in the trace log
"""
require Logger
alias Grizzly.{Trace, ZWave}
alias Grizzly.ZWave.Command
alias Grizzly.ZWave.Commands.ZIPPacket
@type t() :: %__MODULE__{
timestamp: Time.t(),
binary: binary(),
src: Trace.src() | nil,
dest: Trace.dest() | nil
}
@type opt() :: {:src, Trace.src()} | {:dest, Trace.dest()} | {:timestamp, Time.t()}
defstruct src: nil, dest: nil, binary: nil, timestamp: nil
@doc """
Make a new `Grizzly.Record.t()` from a binary string
Options:
* `:src` - the src as a string
* `:dest` - the dest as a string
"""
@spec new(binary(), [opt()]) :: t()
def new(binary, opts \\ []) do
timestamp = Keyword.get(opts, :timestamp, Time.utc_now())
src = Keyword.get(opts, :src)
dest = Keyword.get(opts, :dest)
%__MODULE__{
src: src,
dest: dest,
binary: binary,
timestamp: timestamp
}
end
@doc """
Turn a record into the string format
"""
@spec to_string(t(), Trace.format()) :: String.t()
def to_string(record, format \\ :text)
def to_string(record, :text) do
%__MODULE__{timestamp: ts, src: src, dest: dest, binary: binary} = record
ts = Time.truncate(ts, :millisecond)
prefix = "#{Time.to_string(ts)} #{src_to_string(src)} -> #{dest_to_string(dest)}"
case ZWave.from_binary(binary) do
{:ok, zip_packet} ->
"#{prefix} #{command_info_str(zip_packet, binary)}"
{:error, _} ->
"#{prefix} #{inspect(binary, limit: 500)}"
end
end
def to_string(record, :raw) do
%__MODULE__{timestamp: ts, src: src, dest: dest, binary: binary} = record
time = ts |> Time.truncate(:millisecond) |> Time.to_string()
"#{time} #{src_to_string(src)} -> #{dest_to_string(dest)}: #{inspect(binary, limit: 500)}"
end
defp src_to_string(:grizzly), do: src_to_string("G")
defp src_to_string(src), do: src |> Kernel.to_string() |> String.pad_leading(3)
defp dest_to_string(:grizzly), do: dest_to_string("G")
defp dest_to_string(dest), do: dest |> Kernel.to_string() |> String.pad_trailing(3)
defp command_info_str(%Command{name: :keep_alive} = cmd, _binary) do
case Command.param!(cmd, :ack_flag) do
:ack_request ->
" keep_alive (ack req)"
_ ->
" keep_alive (ack resp)"
end
end
defp command_info_str(zip_packet, binary) do
seq_number = Command.param!(zip_packet, :seq_number)
flag = Command.param!(zip_packet, :flag)
cond do
flag == :nack_waiting ->
expected_delay = ZIPPacket.extension(zip_packet, :expected_delay, nil)
command_info_empty_response(seq_number, flag) <>
" expected_delay=#{inspect(expected_delay)}"
flag in [:ack_response, :nack_response, :nack_waiting] ->
command_info_empty_response(seq_number, flag)
Command.param(zip_packet, :command) == nil ->
" no_operation"
true ->
command_info_with_encapsulated_command(seq_number, zip_packet, binary)
end
end
defp command_info_empty_response(seq_number, flag) do
"#{seq_number_to_str(seq_number)} #{flag}"
end
defp command_info_with_encapsulated_command(seq_number, zip_packet, binary) do
command = Command.param!(zip_packet, :command)
command_binary = ZIPPacket.unwrap(binary)
"#{seq_number_to_str(seq_number)} #{command.name} #{inspect(command_binary, limit: 500)}"
rescue
err ->
Logger.error("""
[Grizzly.Trace] Expected an encapsulated command, but no command param was found.
Binary: #{inspect(binary, limit: 500)}
This is probably a bug -- please report it along with the stack trace and, if
possible, the corresponding line in the trace file.
#{Exception.format(:error, err, __STACKTRACE__)}
""")
command_name =
try do
zip_packet.name
rescue
_ -> "UNKNOWN COMMAND"
end
"#{seq_number_to_str(seq_number)} ENCODING ERROR #{command_name} #{inspect(binary, limit: 500)}"
end
defp seq_number_to_str(seq_number) do
String.pad_trailing(Kernel.to_string(seq_number), 4, " ")
end
end