-
Notifications
You must be signed in to change notification settings - Fork 9
/
meter_reset.ex
90 lines (76 loc) · 2.92 KB
/
meter_reset.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
defmodule Grizzly.ZWave.Commands.MeterReset do
@moduledoc """
This module implements the command METER_RESET of the METER command class.
This command is used to reset all accumulated measurements stored at the receiving node to 0 (v1)
or possibly only a smeasurement to a given value (v6).
## Parameters
* `:meter_type` - the type of metering physical unit being reset (v6)
* `scale` - the scale of the value (v6)
* `:rate_type` - whether the import or export value is being reset (v6)
* `:value` - the value to be reset to (v6)
"""
@behaviour Grizzly.ZWave.Command
alias Grizzly.ZWave.{Command, DecodeError, Encoding}
alias Grizzly.ZWave.CommandClasses.Meter
@type param :: {:meter_type, any()} | {:rate_type, any()} | {:values, any()}
@impl Grizzly.ZWave.Command
@spec new([param()]) :: {:ok, Command.t()}
def new(params) do
command = %Command{
name: :meter_reset,
command_byte: 0x05,
command_class: Meter,
params: params,
impl: __MODULE__
}
{:ok, command}
end
@impl Grizzly.ZWave.Command
@spec encode_params(Command.t()) :: binary()
def encode_params(command) do
if Command.has_param?(command, :meter_type) || Command.has_param?(command, :rate_type) ||
Command.has_param?(command, :scale) || Command.has_param?(command, :value) do
rate_type = Command.param!(command, :rate_type)
meter_type = Command.param!(command, :meter_type)
value = Command.param!(command, :value)
scale = Command.param!(command, :scale)
rate_type_bin = Meter.encode_rate_type(rate_type)
meter_type_bin = Meter.encode_meter_type(meter_type)
{scale1, scale2} = Meter.encode_meter_scale(scale, meter_type)
{int_value, precision, byte_size} = Encoding.encode_zwave_float(value)
<<_::5, scale1_msb::1, scale1_rest::2>> = <<scale1>>
<<scale1_msb::1, rate_type_bin::2, meter_type_bin::5, precision::3, scale1_rest::2,
byte_size::3, int_value::size(byte_size)-unit(8), scale2::8>>
else
<<>>
end
end
@impl Grizzly.ZWave.Command
@spec decode_params(binary()) :: {:ok, [param()]} | {:error, DecodeError.t()}
# v2-v5
def decode_params(<<>>) do
{:ok, []}
end
# v6
def decode_params(
<<scale1_msb::1, rate_type_bin::2, meter_type_bin::5, precision::3, scale1_rest::2,
size::3, int_value::size(size)-unit(8), scale2::8>>
) do
<<scale1>> = <<0::5, scale1_msb::1, scale1_rest::2>>
value = Encoding.decode_zwave_float(int_value, precision)
with {:ok, meter_type} <- Meter.decode_meter_type(meter_type_bin),
{:ok, rate_type} <- Meter.decode_rate_type(rate_type_bin),
{:ok, scale} <- Meter.decode_meter_scale({scale1, scale2}, meter_type) do
{:ok,
[
meter_type: meter_type,
scale: scale,
value: value,
rate_type: rate_type
]}
else
{:error, %DecodeError{}} = error ->
error
end
end
end