defmodule Grizzly.ZWave.DeviceClass do
@moduledoc """
Z-Wave device classes
Z-Wave device classes allow grouping devices with the same functionality
together. Moreover, the device class specification for specific device classes
provide mandatory and recommended command class support.
"""
alias Grizzly.ZWave.{CommandClasses, DeviceClasses}
alias Grizzly.ZWave.Commands.VersionReport
@type command_class_version() :: integer()
@type command_class_spec() :: %{
support: %{required(CommandClasses.command_class()) => command_class_version()},
control: %{required(CommandClasses.command_class()) => command_class_version()}
}
@type t() :: %{
basic_device_class: DeviceClasses.basic_device_class(),
generic_device_class: DeviceClasses.generic_device_class(),
specific_device_class: DeviceClasses.specific_device_class(),
command_classes: command_class_spec(),
manufacturer_id: non_neg_integer(),
product_id: non_neg_integer(),
product_type_id: non_neg_integer(),
library_type: VersionReport.library_type()
}
@doc """
Get the command class version for the command class
"""
@spec get_command_class_version(t(), CommandClasses.command_class()) :: non_neg_integer() | nil
def get_command_class_version(device_class, command_class) do
device_class.command_classes.control
|> Map.merge(device_class.command_classes.support)
|> Enum.find_value(fn
{^command_class, version} -> version
_ -> nil
end)
end
@doc """
Check if the device class specification includes a particular command class
"""
@spec has_command_class?(t(), CommandClasses.command_class()) :: boolean()
def has_command_class?(device_class, command_class) do
device_class.command_classes.control
|> Map.merge(device_class.command_classes.support)
|> Enum.find_value(fn
{^command_class, _version} -> true
_ -> false
end)
end
@doc """
A device class for a HVAC thermostat
"""
@spec thermostat_hvac() :: t()
def thermostat_hvac() do
%{
basic_device_class: :routing_end_node,
generic_device_class: :thermostat,
specific_device_class: :thermostat_general_v2,
command_classes: %{
support: %{
alarm: 3,
association: 2,
association_group_information: 1,
basic: 1,
battery: 1,
device_reset_locally: 1,
manufacturer_specific: 2,
power_level: 1,
security_2: 1,
supervision: 1,
thermostat_mode: 3,
thermostat_fan_mode: 1,
thermostat_fan_state: 1,
thermostat_setpoint: 2,
transport_service: 2,
sensor_multilevel: 5,
version: 2,
zwave_plus_info: 2
},
control: %{}
},
manufacturer_id: 0x0000,
product_id: 0x0000,
product_type_id: 0x0000,
library_type: :routing_end_node
}
end
@doc """
Device class spec for a generic multilevel sensor
"""
@spec multilevel_sensor() :: t()
def multilevel_sensor() do
%{
basic_device_class: :routing_end_node,
generic_device_class: :sensor_multilevel,
specific_device_class: :routing_sensor_multilevel,
command_classes: %{
support: %{
alarm: 3,
association: 2,
association_group_information: 1,
basic: 1,
battery: 1,
device_reset_locally: 1,
manufacturer_specific: 2,
security_2: 1,
sensor_multilevel: 5,
version: 2,
zwave_plus_info: 2
},
control: %{}
},
manufacturer_id: 0x0000,
product_id: 0x0000,
product_type_id: 0x0000,
library_type: :routing_end_node
}
end
end