Packages
grizzly
0.20.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/zwave/command_classes/sensor_multilevel.ex
defmodule Grizzly.ZWave.CommandClasses.SensorMultilevel do
@moduledoc """
"SensorMultilevel" Command Class
The Multilevel Sensor Command Class is used to advertise numerical sensor readings.
"""
@behaviour Grizzly.ZWave.CommandClass
alias Grizzly.ZWave.DecodeError
@sensor_types [
# byte 1
[
:air_temperature,
:general_purpose,
:luminance,
:power,
:humidity,
:velocity,
:direction,
:atmospheric_pressure
],
# byte 2
[
:barometric_pressure,
:solar_radiation,
:dew_point,
:rain_rate,
:tide_level,
:weight,
:voltage,
:current
],
# byte 3
[
:carbon_dioxide_level,
:air_flow,
:tank_capacity,
:distance,
:angle_position,
:rotation,
:water_temperature,
:soil_temperature
],
# byte 4
[
:seismic_intensity,
:seismic_magnitude,
:ultraviolet,
:electrical_resistivity,
:electrical_conductivity,
:loudness,
:moisture,
:frequency
],
# byte 5
[
:time,
:target_temperature,
:particulate_matter_2_5,
:formaldehyde_level,
:radon_concentration,
:methane_density,
:volatile_organic_compound_level,
:carbon_monoxide_level
],
# byte 6
[
:soil_humidity,
:soil_reactivity,
:soil_salinity,
:heart_rate,
:blood_pressure,
:muscle_mass,
:fat_mass,
:bone_mass
],
# byte 7
[
:total_body_water,
:basis_metabolic_rate,
:body_mass_index,
:acceleration_x_axis,
:acceleration_y_axis,
:acceleration_z_axis,
:smoke_density,
:water_flow
],
# byte 8
[
:water_pressure,
:rf_signal_strength,
:particulate_matter_10,
:respiratory_rate,
:relative_modulation_level,
:boiler_water_temperature,
:domestic_hot_water_temperature,
:outside_temperature
],
# byte 9
[
:exhaust_temperature,
:water_chlorine_level,
:water_acidity,
:water_oxidation_reduction_potential,
:heart_rate_lf_hf_ratio,
:motion_direction,
:applied_force,
:return_air_temperature
],
# byte 10
[
:supply_air_temperature,
:condensor_coil_temperature,
:evaporator_coil_temperature,
:liquid_line_temperature,
:discharge_line_temperature,
:suction_pressure,
:discharge_pressure,
:defrost_temperature
],
# byte 11
[
:ozone,
:sulfur_dioxide,
:nitrogen_dioxide,
:ammonia,
:lead,
:particulate_matter_1,
:unknown,
:unknown
]
]
@impl true
def byte(), do: 0x31
@impl true
def name(), do: :sensor_multilevel
def encode_sensor_type(:temperature), do: 0x01
def encode_sensor_type(:general), do: 0x02
def encode_sensor_type(:luminance), do: 0x03
def encode_sensor_type(:power), do: 0x04
def encode_sensor_type(:humidity), do: 0x05
def encode_sensor_type(:velocity), do: 0x06
def encode_sensor_type(:direction), do: 0x07
def encode_sensor_type(:atmospheric_pressure), do: 0x08
def encode_sensor_type(:barometric_pressure), do: 0x09
def encode_sensor_type(:solar_radiation), do: 0x0A
def encode_sensor_type(:dew_point), do: 0x0B
def encode_sensor_type(:rain_rate), do: 0x0C
def encode_sensor_type(:tide_level), do: 0x0D
def encode_sensor_type(:weight), do: 0x0E
def encode_sensor_type(:voltage), do: 0x0F
def encode_sensor_type(:current), do: 0x10
def encode_sensor_type(:co2_level), do: 0x11
def encode_sensor_type(:air_flow), do: 0x12
def encode_sensor_type(:tank_capacity), do: 0x13
def encode_sensor_type(:distance), do: 0x14
def encode_sensor_type(:angle_position), do: 0x15
def encode_sensor_type(:rotation), do: 0x16
def encode_sensor_type(:water_temperature), do: 0x17
def encode_sensor_type(:soil_temperature), do: 0x18
def encode_sensor_type(:seismic_intensity), do: 0x19
def encode_sensor_type(:seismic_magnitude), do: 0x1A
def encode_sensor_type(:ultraviolet), do: 0x1B
def encode_sensor_type(:electrical_resistivity), do: 0x1C
def encode_sensor_type(:electrical_conductivity), do: 0x1D
def encode_sensor_type(:loudness), do: 0x1E
def encode_sensor_type(:moisture), do: 0x1F
def encode_sensor_type(:frequency), do: 0x20
def encode_sensor_type(:time), do: 0x21
def encode_sensor_type(:target_temperature), do: 0x22
def decode_sensor_type(0x01), do: {:ok, :temperature}
def decode_sensor_type(0x02), do: {:ok, :general}
def decode_sensor_type(0x03), do: {:ok, :luminance}
def decode_sensor_type(0x04), do: {:ok, :power}
def decode_sensor_type(0x05), do: {:ok, :humidity}
def decode_sensor_type(0x06), do: {:ok, :velocity}
def decode_sensor_type(0x07), do: {:ok, :direction}
def decode_sensor_type(0x08), do: {:ok, :atmospheric_pressure}
def decode_sensor_type(0x09), do: {:ok, :barometric_pressure}
def decode_sensor_type(0x0A), do: {:ok, :solar_radiation}
def decode_sensor_type(0x0B), do: {:ok, :dew_point}
def decode_sensor_type(0x0C), do: {:ok, :rain_rate}
def decode_sensor_type(0x0D), do: {:ok, :tide_level}
def decode_sensor_type(0x0E), do: {:ok, :weight}
def decode_sensor_type(0x0F), do: {:ok, :voltage}
def decode_sensor_type(0x10), do: {:ok, :current}
def decode_sensor_type(0x11), do: {:ok, :co2_level}
def decode_sensor_type(0x12), do: {:ok, :air_flow}
def decode_sensor_type(0x13), do: {:ok, :tank_capacity}
def decode_sensor_type(0x14), do: {:ok, :distance}
def decode_sensor_type(0x15), do: {:ok, :angle_position}
def decode_sensor_type(0x16), do: {:ok, :rotation}
def decode_sensor_type(0x17), do: {:ok, :water_temperature}
def decode_sensor_type(0x18), do: {:ok, :soil_temperature}
def decode_sensor_type(0x19), do: {:ok, :seismic_intensity}
def decode_sensor_type(0x1A), do: {:ok, :seismic_magnitude}
def decode_sensor_type(0x1B), do: {:ok, :ultraviolet}
def decode_sensor_type(0x1C), do: {:ok, :electrical_resistivity}
def decode_sensor_type(0x1D), do: {:ok, :electrical_conductivity}
def decode_sensor_type(0x1E), do: {:ok, :loudness}
def decode_sensor_type(0x1F), do: {:ok, :moisture}
def decode_sensor_type(0x20), do: {:ok, :frequency}
def decode_sensor_type(0x21), do: {:ok, :time}
def decode_sensor_type(0x22), do: {:ok, :target_temperature}
def decode_sensor_type(byte),
do:
{:error, %DecodeError{value: byte, param: :sensor_type, command: :sensor_multilevel_report}}
@spec decode_sensor_types(binary) :: {:ok, [sensor_types: [atom]]} | {:error, %DecodeError{}}
def decode_sensor_types(binary) do
sensor_types =
:binary.bin_to_list(binary)
|> Enum.map(&bit_set_indices(<<&1>>))
|> Enum.with_index()
|> Enum.map(fn {bit_indices, byte} -> Enum.map(bit_indices, &decode_sensor(byte, &1)) end)
|> List.flatten()
if Enum.any?(sensor_types, &(&1 == nil)) do
{:error,
%DecodeError{
value: binary,
param: :sensor_types,
command: :sensor_multilevel_supported_sensor_report
}}
else
{:ok, [sensor_types: sensor_types]}
end
end
@spec encode_sensor_types([atom]) :: binary
def encode_sensor_types(sensor_types) do
for bit_list <- byte_indices(sensor_types) do
for bit <- Enum.reverse(bit_list), into: <<>>, do: <<bit::1>>
end
|> :binary.list_to_bin()
end
defp byte_indices(sensor_types) do
for byte <- (Enum.count(@sensor_types) - 1)..0 do
sensor_types_per_byte = Enum.at(@sensor_types, byte)
for index <- 0..7 do
if Enum.at(sensor_types_per_byte, index) in sensor_types, do: 1, else: 0
end
end
|> Enum.drop_while(fn indices -> Enum.all?(indices, &(&1 == 0)) end)
|> Enum.reverse()
end
defp bit_set_indices(byte) do
for(<<x::1 <- byte>>, do: x)
|> Enum.reverse()
|> Enum.with_index()
|> Enum.reduce([], fn {bit, index}, acc ->
if bit == 1, do: [index | acc], else: acc
end)
end
defp decode_sensor(byte, bit_index) do
Enum.at(@sensor_types, byte) |> Enum.at(bit_index)
end
end