Packages
grizzly
8.5.2
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.src() | 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
prefix = "#{Time.to_string(ts)} #{src_dest_to_string(src)} #{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_dest_to_string(src)} -> #{src_dest_to_string(dest)}: #{inspect(binary, limit: 500)}"
end
defp src_dest_to_string(nil) do
Enum.reduce(1..18, "", fn _, str -> str <> " " end)
end
defp src_dest_to_string(src_or_dest), do: src_or_dest
defp command_info_str(%Command{name: :keep_alive}, _binary) do
" keep_alive"
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
case seq_number do
seq_number when seq_number < 10 ->
"#{seq_number} "
seq_number when seq_number < 100 ->
"#{seq_number} "
seq_number ->
"#{seq_number}"
end
end
end