Packages
grizzly
0.11.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/zwave/notifications.ex
defmodule Grizzly.ZWave.Notifications do
alias Grizzly.ZWave.Commands.UserCodeReport
alias Grizzly.ZWave.CommandClasses.UserCode
alias Grizzly.ZWave.{Decoder, DecodeError}
require Logger
defmodule Generate do
@moduledoc false
@table [
# {type_byte, type, event_byte, event}
# Smoke Alarm (0x01)
{0x01, :smoke_alarm, 0x00, :state_idle},
{0x01, :smoke_alarm, 0x01, :smoke_detected_location_provided},
{0x01, :smoke_alarm, 0x02, :smoked_detected},
{0x01, :smoke_alarm, 0x03, :smoke_alarm_test},
{0x01, :smoke_alarm, 0x04, :replacement_required},
{0x01, :smoke_alarm, 0x05, :replacement_required_end_of_life},
{0x01, :smoke_alarm, 0x06, :alarm_silenced},
{0x01, :smoke_alarm, 0x07, :maintenance_required_planned_periodic_inspection},
{0x01, :smoke_alarm, 0x08, :maintenance_required_dust_in_device},
# Water (0x05)
{0x05, :water, 0x00, :state_idle},
{0x05, :water, 0x01, :water_leak_detected_known_location},
{0x05, :water, 0x02, :water_leak_detected},
{0x05, :water, 0x03, :water_level_dropped_known_location},
{0x05, :water, 0x04, :water_level_dropped},
{0x05, :water, 0x05, :replace_water_filter},
{0x05, :water, 0x06, :water_flow_alarm},
{0x05, :water, 0x07, :water_pressure_alarm},
{0x05, :water, 0x08, :water_temperature_alarm},
{0x05, :water, 0x09, :water_level_alarm},
{0x05, :water, 0x0A, :sump_pump_active},
{0x05, :water, 0x0B, :sump_pump_failure},
{0x05, :water, 0xFE, :unknown},
# Access Control (0x06)
{0x06, :access_control, 0x00, :state_idle},
{0x06, :access_control, 0x01, :manual_lock_operation},
{0x06, :access_control, 0x02, :manual_unlock_operation},
{0x06, :access_control, 0x03, :rf_lock_operation},
{0x06, :access_control, 0x04, :rf_unlock_operation},
{0x06, :access_control, 0x05, :keypad_lock_operation},
{0x06, :access_control, 0x06, :keypad_unlock_operation},
{0x06, :access_control, 0x07, :manual_not_fully_locked_operation},
{0x06, :access_control, 0x08, :rf_not_fully_locked_operation},
{0x06, :access_control, 0x09, :auto_lock_locked_operation},
{0x06, :access_control, 0x0A, :auto_lock_not_fully_locked_operation},
{0x06, :access_control, 0x0B, :lock_jammed},
{0x06, :access_control, 0x0C, :all_user_codes_deleted},
{0x06, :access_control, 0x0D, :single_user_code_deleted},
{0x06, :access_control, 0x0E, :new_user_code_added},
{0x06, :access_control, 0x0F, :new_user_code_not_added_duplicate},
{0x06, :access_control, 0x10, :keypad_temporarily_disabled},
{0x06, :access_control, 0x11, :keypad_busy},
{0x06, :access_control, 0x12, :new_program_code_entered},
{0x06, :access_control, 0x13, :manually_enter_user_code_exceeds_code_limit},
{0x06, :access_control, 0x14, :unlock_by_rf_with_invalid_user_code},
{0x06, :access_control, 0x15, :locked_by_rf_with_invalid_user_code},
{0x06, :access_control, 0x16, :window_or_door_is_open},
{0x06, :access_control, 0x17, :window_or_door_is_closed},
{0x06, :access_control, 0x18, :window_or_door_handle_is_open},
{0x06, :access_control, 0x19, :window_or_door_handle_is_closed},
{0x06, :access_control, 0x20, :messaging_user_code_entered_via_keypad},
{0x06, :access_control, 0x40, :barrier_performing_initialization_process},
{0x06, :access_control, 0x41, :barrier_operation_exceeded_time_limit},
{0x06, :access_control, 0x42, :barrier_operation_force_exceeded},
{0x06, :access_control, 0x43, :barrier_operation_exceeded_mechanical_limit},
{0x06, :access_control, 0x44, :barrier_unable_to_perform_operation_ul_requirements},
{0x06, :access_control, 0x45, :barrier_unattended_operation_disabled_ul_requirements},
{0x06, :access_control, 0x46, :barrier_failed_operation_malfunction},
{0x06, :access_control, 0x47, :barrier_vacation_mode},
{0x06, :access_control, 0x48, :barrier_safety_beam_obstacle},
{0x06, :access_control, 0x49, :barrier_sensor_not_detected},
{0x06, :access_control, 0x4A, :barrier_sensor_low_battery},
{0x06, :access_control, 0x4B, :barrier_short_in_wall_station_wires},
# Home Security (0x07)
{0x07, :home_security, 0x00, :state_idle},
{0x07, :home_security, 0x01, :intrusion_location_provided},
{0x07, :home_security, 0x02, :intrusion},
{0x07, :home_security, 0x03, :tampering_product_cover_removed},
{0x07, :home_security, 0x04, :tampering_invalid_code},
{0x07, :home_security, 0x05, :glass_breakage_location_provided},
{0x07, :home_security, 0x06, :glass_breakage},
{0x07, :home_security, 0x07, :motion_detection},
{0x07, :home_security, 0x08, :motion_detection_location_provided},
{0x07, :home_security, 0x09, :tampering_product_moved},
{0x07, :home_security, 0x0A, :impact_detected},
{0x07, :home_security, 0x0B, :magnetic_field_interface_detected},
{0x07, :home_security, 0xFE, :unknown_state},
# Siren (0x0E)
{0x0E, :siren, 0x00, :state_idle},
{0x0E, :siren, 0x01, :state_active}
]
defmacro __before_compile__(_) do
type_to_byte =
for {alarm_type_byte, alarm_type_name, _, _} <-
Enum.uniq_by(@table, fn {_, type, _, _} -> type end) do
quote do
def type_to_byte(unquote(alarm_type_name)), do: unquote(alarm_type_byte)
end
end
event_to_byte =
for {_alarm_type_byte, alarm_type_name, alarm_event_byte, alarm_event_name} <- @table do
quote do
def event_to_byte(unquote(alarm_type_name), unquote(alarm_event_name)) do
unquote(alarm_event_byte)
end
end
end
type_from_byte =
for {alarm_type_byte, alarm_type_name, _, _} <-
Enum.uniq_by(@table, fn {byte, _, _, _} -> byte end) do
quote do
def type_from_byte(unquote(alarm_type_byte)), do: {:ok, unquote(alarm_type_name)}
end
end
event_from_byte =
for {_, type, event_byte, event} <- @table do
quote do
def event_from_byte(unquote(type), unquote(event_byte)), do: {:ok, unquote(event)}
end
end
quote do
@type event :: atom()
@type type :: atom()
@doc """
Get the byte for the event name
"""
@spec type_to_byte(type()) :: byte()
unquote(type_to_byte)
@doc """
Get the event byte given the event type
"""
@spec event_to_byte(type(), event()) :: byte()
unquote(event_to_byte)
@doc """
Get the type from the byte
"""
@spec type_from_byte(byte()) :: {:ok, type()} | {:error, :invalid_type_byte}
unquote(type_from_byte)
def type_from_byte(_), do: {:error, :invalid_type_byte}
@doc """
Get the event from the byte given the notification type
"""
@spec event_from_byte(type(), byte()) :: {:ok, event()} | {:error, :invalid_event_byte}
unquote(event_from_byte)
def event_from_byte(_, _), do: {:error, :invalid_event_byte}
end
end
end
@type zwave_alarm_status :: :deactivate | :activate
@before_compile Generate
def encode_event_params(_zwave_type, _zwave_event, []), do: <<>>
def encode_event_params(:access_control, zwave_event, event_params_list)
when zwave_event in [:keypad_lock_operation, :keypad_unlock_operation] do
{:ok, user_code_report} = UserCodeReport.new(event_params_list)
<<UserCode.byte(), user_code_report.command_byte>> <>
UserCodeReport.encode_params(user_code_report)
end
def encode_event_params(zwave_type, zwave_event, event_params) do
Logger.info(
"[Grizzly] Encoding not implemented for event params #{inspect(event_params)} for zwave_type #{
inspect(zwave_type)
} and zwave_event #{inspect(zwave_event)}"
)
<<>>
end
def decode_event_params(_zwave_type, _zwave_event, <<>>), do: {:ok, []}
def decode_event_params(:access_control, zwave_event, params_binary)
when zwave_event in [:keypad_lock_operation, :keypad_unlock_operation] do
with {:ok, user_code_report} <- Decoder.from_binary(params_binary) do
{:ok, user_code_report.params}
else
{:error, %DecodeError{}} = decode_error ->
Logger.warn("[Grizzly] Failed to decode UserCodeReport from #{inspect(params_binary)}")
decode_error
end
end
def decode_event_params(zwave_type, zwave_event, params_binary) do
Logger.info(
"Decoding not implemented for event params #{inspect(params_binary)} for zwave_type #{
inspect(zwave_type)
} and zwave_event #{inspect(zwave_event)}"
)
{:ok, []}
end
end