# `Grizzly.ZWave.Encoding`
[🔗](https://github.com/smartrent/grizzly/blob/v9.1.4/lib/grizzly/zwave/encoding.ex#L1)

Utility functions for encoding/decoding common data types.

# `duration`

```elixir
@type duration() :: 0..7560 | :unknown | :default
```

Common representation for durations used in Z-Wave command classes.

Durations of 0..127 seconds are encoded with 1-second resolution. Durations of
128..7560 seconds are encoded with 1-minute resolution. Larger durations are
not supported and will be encoded as unknown (0xFE).

See section 2.1.7.3 of the Z-Wave Specification for details.

# `encode_bitmask_opts`

```elixir
@type encode_bitmask_opts() :: [{:min_bytes, non_neg_integer()}]
```

# `string_encoding`

```elixir
@type string_encoding() :: :ascii | :extended_ascii | :utf16
```

# `binary_sensor_types`

```elixir
@spec binary_sensor_types() :: Grizzly.ZWave.ZWEnum.t()
```

# `bit_to_bool`

```elixir
@spec bit_to_bool(0 | 1) :: boolean()
```

Converts a bit into a boolean.

## Examples

    iex> bit_to_bool(1)
    true
    iex> bit_to_bool(0)
    false

# `bool_to_bit`

```elixir
@spec bool_to_bit(boolean()) :: 0 | 1
```

Converts a boolean into a bit.

## Examples

    iex> bool_to_bit(true)
    1
    iex> bool_to_bit(false)
    0

# `credential_learn_statuses`

# `decode_bitmask`

```elixir
@spec decode_bitmask(binary()) :: [non_neg_integer()]
```

Decodes an indexed bitmask.

### Examples

    iex> decode_bitmask(<<>>)
    []

    iex> decode_bitmask(<<0b10110001, 0, 0>>)
    [0, 4, 5, 7]

    iex> decode_bitmask(<<0b10110001, 0b00000001, 0, 0, 0b00001000>>)
    [0, 4, 5, 7, 8, 35]

# `decode_duration`

```elixir
@spec decode_duration(byte()) :: duration()
```

Decodes a duration as encoded by `encode_duration/1`. Returns `:unknown` if
the value is outside the range 0x00..0xFD or `:default` for 0xFF.

## Examples

    iex> decode_duration(0x00)
    0
    iex> decode_duration(0x2D)
    45
    iex> decode_duration(0x7F)
    127
    iex> decode_duration(0x80)
    60
    iex> decode_duration(0x81)
    120
    iex> decode_duration(0x82)
    180
    iex> decode_duration(0xFD)
    7560
    iex> decode_duration(0xFE)
    :unknown
    iex> decode_duration(0xFF)
    :default

# `decode_enum_bitmask`

```elixir
@spec decode_enum_bitmask(Grizzly.ZWave.ZWEnum.t(), bitstring()) :: [
  Grizzly.ZWave.ZWEnum.k()
]
```

Decodes a list of keys from a bitmask using the provided `Grizzly.ZWave.ZWEnum`
to map keys to bit positions.

## Examples

    iex> enum = Grizzly.ZWave.ZWEnum.new(foo: 1, bar: 2, baz: 7, qux: 8)
    iex> decode_enum_bitmask(enum, <<0b10000010, 0b1>>)
    [:foo, :baz, :qux]

# `decode_ipv6_address`

```elixir
@spec decode_ipv6_address(binary()) :: :inet.ip6_address()
```

Decodes a 128-bit binary into an IPv6 address tuple.

## Examples

    iex> decode_ipv6_address(<<0xfd00::16, 0xaaaa::16, 0::16, 0::16, 0::16, 0::16, 0::16, 2::16>>)
    {0xfd00, 0xaaaa, 0, 0, 0, 0, 0, 2}

# `decode_string`

```elixir
@spec decode_string(binary(), string_encoding()) :: binary()
```

Decodes a binary string into a UTF-8 string using the specified encoding type.

# `decode_string_encoding`

```elixir
@spec decode_string_encoding(byte()) :: string_encoding() | :unknown
```

Decodes a string encoding type from a byte value.

# `decode_zwave_float`

```elixir
@spec decode_zwave_float(integer(), non_neg_integer()) :: number()
```

Converts an integer value and non-zero precision into a float by dividing the
integer by `10 ^ precision`. If the given precision is zero, the integer is
returned as-is.

## Examples

    iex> decode_zwave_float(0, 0)
    0
    iex> decode_zwave_float(0, 2)
    0.0
    iex> decode_zwave_float(1234, 2)
    12.34
    iex> decode_zwave_float(1234, 1)
    123.4
    iex> decode_zwave_float(1234, 0)
    1234
    iex> decode_zwave_float(-1234, 2)
    -12.34

# `door_lock_modes`

```elixir
@spec door_lock_modes() :: Grizzly.ZWave.ZWEnum.t()
```

# `encode_bitmask`

```elixir
@spec encode_bitmask([non_neg_integer()], encode_bitmask_opts()) :: binary()
```

Encodes a list into a bitmask.

### Examples

    iex> encode_bitmask([])
    <<>>

    iex> encode_bitmask([0, 4, 5, 7, 8, 35])
    <<0b10110001, 0b00000001, 0, 0, 0b00001000>>

    iex> encode_bitmask([31, 8, 5, 0, 4, 7])
    <<0b10110001, 0b00000001, 0b00000000, 0b10000000>>

    iex> encode_bitmask([0, 4, 5, 7], min_bytes: 3)
    <<0b10110001, 0, 0>>

# `encode_duration`

```elixir
@spec encode_duration(duration()) :: byte()
```

Encodes a duration in seconds into a duration byte.

Durations of 0..127 seconds are encoded with 1-second resolution. Durations of
128..7560 seconds are encoded with 1-minute resolution, **rounded to the nearest
minute**. Larger durations are not supported and will be encoded as unknown (0xFE).

Some command classes also support a device-default duration (0xFF), which can
be specified using `:default`.

## Examples

    iex> encode_duration(0)
    0x00
    iex> encode_duration(45)
    0x2D
    iex> encode_duration(127)
    0x7F
    iex> encode_duration(128)
    0x81
    iex> encode_duration(180)
    0x82
    iex> encode_duration(200)
    0x82
    iex> encode_duration(7560)
    0xFD
    iex> encode_duration(8000)
    0xFE
    iex> encode_duration(:unknown)
    0xFE
    iex> encode_duration(:default)
    0xFF

# `encode_enum_bitmask`

```elixir
@spec encode_enum_bitmask(
  Grizzly.ZWave.ZWEnum.t(),
  [Grizzly.ZWave.ZWEnum.k()],
  encode_bitmask_opts()
) ::
  bitstring()
```

Encodes a list of keys into a bitmask using the provided `Grizzly.ZWave.ZWEnum`
to map keys to bit positions.

## Examples

    iex> enum = Grizzly.ZWave.ZWEnum.new(foo: 1, bar: 2, baz: 7, qux: 8)
    iex> encode_enum_bitmask(enum, [:foo, :baz, :qux])
    <<0b10000010, 0b1>>

# `encode_ipv6_address`

```elixir
@spec encode_ipv6_address(:inet.ip6_address()) :: binary()
```

Encodes an IPv6 address tuple into a 128-bit binary.

## Examples

    iex> encode_ipv6_address({0xfd00, 0xaaaa, 0, 0, 0, 0, 0, 2})
    <<0xfd00::16, 0xaaaa::16, 0::16, 0::16, 0::16, 0::16, 0::16, 2::16>>

# `encode_string`

```elixir
@spec encode_string(binary(), string_encoding()) :: binary()
```

Encodes a UTF-8 string using the specified encoding type.

ASCII and extended ASCII encodings remove non-ASCII characters, while
UTF-16 encoding converts the string to a UTF-16 binary representation.

# `encode_string_encoding`

```elixir
@spec encode_string_encoding(string_encoding()) :: byte()
```

Encodes a string encoding type to a byte value.

Uses the representation defined in the Node Naming and User Credential command
classes.

# `encode_zwave_float`

```elixir
@spec encode_zwave_float(value :: number()) ::
  {int_value :: integer(), precision :: non_neg_integer(), size :: integer()}
```

Converts a float into a tuple containing an integer representation of the float,
the factor of 10 by which the integer must be divided to get the original float,
and the number of bytes needed to represent the value as a signed integer.

## Examples

    iex> encode_zwave_float(0)
    {0, 0, 1}
    iex> encode_zwave_float(-1.5)
    {-15, 1, 1}
    iex> encode_zwave_float(-1.50)
    {-15, 1, 1}
    iex> encode_zwave_float(128)
    {128, 0, 2}
    iex> encode_zwave_float(127.5)
    {1275, 1, 2}
    iex> encode_zwave_float(-75.25)
    {-7525, 2, 2}
    iex> encode_zwave_float(-752.55)
    {-75255, 2, 4}
    iex> encode_zwave_float(-75.255)
    {-75255, 3, 4}

# `humidity_control_modes`

```elixir
@spec humidity_control_modes() :: Grizzly.ZWave.ZWEnum.t()
```

# `humidity_control_operating_states`

```elixir
@spec humidity_control_operating_states() :: Grizzly.ZWave.ZWEnum.t()
```

# `humidity_control_setpoint_scales`

```elixir
@spec humidity_control_setpoint_scales() :: Grizzly.ZWave.ZWEnum.t()
```

# `humidity_control_setpoint_types`

```elixir
@spec humidity_control_setpoint_types() :: Grizzly.ZWave.ZWEnum.t()
```

# `kex_fail_types`

```elixir
@spec kex_fail_types() :: Grizzly.ZWave.ZWEnum.t()
```

# `multilevel_sensor_types`

```elixir
@spec multilevel_sensor_types() :: Grizzly.ZWave.ZWEnum.t()
```

# `network_update_request_statuses`

```elixir
@spec network_update_request_statuses() :: Grizzly.ZWave.ZWEnum.t()
```

# `power_levels`

```elixir
@spec power_levels() :: Grizzly.ZWave.ZWEnum.t()
```

# `reduce_binary`

```elixir
@spec reduce_binary(binary(), term(), (binary(), acc :: term() -&gt;
                                   {acc :: term(), rest :: binary()})) ::
  acc :: term()
```

Reduce over a binary by repeatedly applying a reducer function until the binary
is empty.

The reducer function should take a binary and an accumulator and return a tuple
`{new_acc, rest}` where `new_acc` is the updated accumulator and `rest` is the
remaining binary to process.

## Examples

    iex> reducer = fn
    ...>   <<word::16, rest::binary>>, acc ->
    ...>     {[word | acc], rest}
    ...>   <<byte, rest::binary>>, acc ->
    ...>     {[byte | acc], rest}
    ...> end
    iex> reduce_binary(<<1, 2, 3>>, [], reducer)
    [3, 258]

# `reduce_binary_while`

```elixir
@spec reduce_binary_while(binary(), term(), (binary(), acc :: term() -&gt;
                                         {:halt | :cont,
                                          {acc :: term(), rest :: binary()}})) ::
  {acc :: term(), rest :: binary()}
```

Reduce over a binary by repeatedly applying a reducer function.

The reducer function should take a binary and an accumulator and return either
`{:cont, {new_acc, rest}}` to continue reducing with the new accumulator and
remaining binary, or `{:halt, {new_acc, rest}}` to stop reducing and return the
final accumulator and remaining binary.

The reduction will halt automatically when the binary is empty.

## Examples

    iex> reducer = fn
    ...>   <<byte, rest::binary>>, acc when byte < 5 ->
    ...>     {:cont, {[byte | acc], rest}}
    ...>   binary, acc ->
    ...>     {:halt, {acc, binary}}
    ...> end
    iex> reduce_binary_while(<<1, 2, 3, 6, 4>>, [], reducer)
    {[3, 2, 1], <<6, 4>>}
    iex> reduce_binary_while(<<1, 2, 3>>, reducer)
    {[3, 2, 1], <<>>}

# `security_key_types`

```elixir
@spec security_key_types() :: Grizzly.ZWave.ZWEnum.t()
```

# `string_encodings`

# `thermostat_fan_modes`

```elixir
@spec thermostat_fan_modes() :: Grizzly.ZWave.ZWEnum.t()
```

# `thermostat_fan_states`

```elixir
@spec thermostat_fan_states() :: Grizzly.ZWave.ZWEnum.t()
```

# `thermostat_operating_states`

# `tz_offset_signs`

```elixir
@spec tz_offset_signs() :: Grizzly.ZWave.ZWEnum.t()
```

# `uc_admin_pin_code_set_statuses`

```elixir
@spec uc_admin_pin_code_set_statuses() :: Grizzly.ZWave.ZWEnum.t()
```

# `uc_association_set_statuses`

```elixir
@spec uc_association_set_statuses() :: Grizzly.ZWave.ZWEnum.t()
```

# `uc_credential_types`

```elixir
@spec uc_credential_types() :: Grizzly.ZWave.ZWEnum.t()
```

# `user_code_keypad_modes`

```elixir
@spec user_code_keypad_modes() :: Grizzly.ZWave.ZWEnum.t()
```

# `zwave_float_to_binary`

```elixir
@spec zwave_float_to_binary(number(), byte()) :: binary()
```

Converts a float into a binary representation of a Z-Wave float according to
the typical format.

* precision (3 bits)
* scale (2 bits)
* size (3 bits)
* value (n bytes, where n = size)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
