Packages
grizzly
5.2.4
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/virtual_devices/temperature_sensor.ex
defmodule Grizzly.VirtualDevices.TemperatureSensor do
@moduledoc """
A virtual device for a temperature sensor
This virtual device reports changes in the sensor every minute using the
`Grizzly.ZWave.Commands.SensorMultilevelReport` command.
If you want a faster or slower reporting interval you can configure the
`:report_interval` option.
"""
@behaviour Grizzly.VirtualDevices.Device
use GenServer
alias Grizzly.VirtualDevices
alias Grizzly.ZWave.{Command, DeviceClass}
alias Grizzly.ZWave.Commands.{
BasicReport,
SensorMultilevelSupportedSensorReport,
SensorMultilevelReport
}
@typedoc """
Init options
* `:report_interval` - the time in milliseconds to read and maybe report temp
changes, default `60_000`
* `:force_report` - report all temperature readings, default false (will only
report if the temperature changed from last reading)
"""
@type opt() :: {:report_interval, non_neg_integer()} | {:force_report, boolean()}
@type state() :: %{
temp: non_neg_integer(),
force_report: boolean(),
device_id: Grizzly.VirtualDevices.id()
}
@impl Grizzly.VirtualDevices.Device
def device_spec(_device_opts) do
DeviceClass.multilevel_sensor()
end
@doc """
Start the temperature sensor
"""
@spec start_link([opt()]) :: GenServer.on_start()
def start_link(opts) do
GenServer.start_link(__MODULE__, opts)
end
@impl GenServer
def init(opts) do
report_interval = opts[:report_interval] || 60_000
force_report = opts[:force_report] || false
_ = :timer.send_interval(report_interval, :send_temp)
{:ok, %{temp: 0, force_report: force_report, device_id: nil}}
end
@impl Grizzly.VirtualDevices.Device
def set_device_id(server, device_id) do
GenServer.cast(server, {:set_device_id, device_id})
end
@impl Grizzly.VirtualDevices.Device
def handle_command(command, device_opts) do
server = Keyword.fetch!(device_opts, :pid)
GenServer.call(server, {:handle_command, command})
end
@impl GenServer
def handle_cast({:set_device_id, device_id}, state) do
{:noreply, %{state | device_id: device_id}}
end
@impl GenServer
def handle_info(:send_temp, state) do
new_temp = read_temp(state)
if state.device_id == nil or (!state.force_report && new_temp == state.temp) do
{:noreply, state}
else
{:ok, command} = build_multilevel_sensor_report(new_temp)
VirtualDevices.broadcast_command(state.device_id, command)
{:noreply, %{state | temp: new_temp}}
end
end
@impl GenServer
def handle_call({:handle_command, %Command{name: :basic_get}}, _from, state) do
report = BasicReport.new(value: state.temp)
{:reply, report, state}
end
def handle_call({:handle_command, %Command{name: :sensor_multilevel_get}}, _from, state) do
{:reply, build_multilevel_sensor_report(state.temp), state}
end
def handle_call(
{:handle_command, %Command{name: :sensor_multilevel_supported_sensor_get}},
_from,
state
) do
result = SensorMultilevelSupportedSensorReport.new(sensor_types: [:temperature])
{:reply, result, state}
end
def handle_call({:handle_command, _unsupported_command}, _from, state) do
{:reply, {:error, :timeout}, state}
end
defp build_multilevel_sensor_report(value) do
# According to the sensor multilevel command class if any scale or sensor
# type requested is not supported we are to respond with a default supported
# type and/or scale. This virtual device only supports temperature and scale 1
# so we will always report those.
SensorMultilevelReport.new(sensor_type: :temperature, scale: 1, value: value)
end
# simulate reading a temperature sensor
defp read_temp(state) do
if Enum.random([true, false]) do
Enum.random(0..99)
else
state.temp
end
end
end