Packages
grizzly
5.2.3
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/qr_code.ex
defmodule Grizzly.ZWave.QRCode do
@moduledoc """
Z-Wave QR code
This module handles Z-Wave QR codes that follow Silicon Labs
Software Design Specification SDS13937 and SDS13944.
"""
alias Grizzly.ZWave
alias Grizzly.ZWave.SmartStart.MetaExtension.UUID16
@typedoc "QR Code version (S2-only or Smart Start-enabled)"
@type version() :: :s2 | :smart_start
@typedoc """
Device information
* `:zwave_device_type` - either {generic_device_type, specific_device_type} or a number
"""
@type t() :: %__MODULE__{
version: version(),
requested_keys: [ZWave.Security.key()],
dsk: ZWave.DSK.t(),
zwave_device_type: {atom(), atom()} | 0..65535,
zwave_installer_icon: ZWave.IconType.name() | ZWave.IconType.value(),
manufacturer_id: 0..65535,
product_type: 0..65535,
product_id: 0..65535,
application_version: 0..65535,
uuid16: nil | UUID16.t()
}
defstruct version: :smart_start,
requested_keys: [],
dsk: ZWave.DSK.zeros(),
zwave_device_type: 0,
zwave_installer_icon: 0,
manufacturer_id: 0,
product_type: 0,
product_id: 0,
application_version: 0,
uuid16: nil
@lead_in "90"
@doc """
Encode device information into Z-Wave QR Code format
The output of this is either a 90 byte or 136 byte string that should be put
into a QR Code. Z-Wave specifies that the 90-byte code (no UUID16) is made
into a 29x29 pixel QR Code. The 136-byte* code (w/ UUID16) should be put into
a 33x33 pixel QR Code.
QR Codes should be encoded as type "text" with error correction "L".
NOTE: SDS13937 has a mistake with the code length. It says 134 bytes, but the
UUID16 encode has 2 extra bytes for presentation, so it should be 136.
"""
@spec encode!(t()) :: iolist()
def encode!(info) do
payload = [
encode_requested_keys(info.requested_keys),
encode_dsk(info),
encode_qr_product_type(info),
encode_qr_product_id(info),
encode_uuid16(info.uuid16)
]
[@lead_in, encode_version(info.version), checksum(payload), payload]
end
defp checksum(payload) do
<<two_bytes::16, _rest::144>> = :crypto.hash(:sha, payload)
int_to_string(two_bytes, 5)
end
defp encode_version(:s2), do: "00"
defp encode_version(:smart_start), do: "01"
defp encode_requested_keys(requested_keys) do
ZWave.Security.keys_to_byte(requested_keys)
|> int_to_string(3)
end
defp encode_dsk(info), do: ZWave.DSK.to_string(info.dsk, delimiter: "")
defp encode_qr_product_type(info) do
# QR Product type = TLV type 00, length 10
[
"0010",
encode_device_type(info.zwave_device_type),
encode_icon_type(info.zwave_installer_icon)
]
end
defp encode_device_type({generic, specific}) do
device_type =
ZWave.DeviceClasses.generic_device_class_to_byte(generic) * 256 +
ZWave.DeviceClasses.specific_device_class_to_byte(generic, specific)
encode_device_type(device_type)
end
defp encode_device_type(device_type) when is_integer(device_type) do
int_to_string(device_type, 5)
end
defp encode_icon_type(type) when is_atom(type) do
{:ok, value} = ZWave.IconType.to_value(type)
encode_icon_type(value)
end
defp encode_icon_type(type), do: int_to_string(type, 5)
defp encode_qr_product_id(info) do
# QR Product ID = TLV type 02, length 20
[
"0220",
int_to_string(info.manufacturer_id, 5),
int_to_string(info.product_type, 5),
int_to_string(info.product_id, 5),
int_to_string(info.application_version, 5)
]
end
defp encode_uuid16(nil), do: []
defp encode_uuid16(uuid16) do
value = UUID16.encode(uuid16)
<<0x06, 0x11, presentation, uuid::binary>> = value
decimalized_uuid =
uuid
|> ZWave.DSK.new()
|> ZWave.DSK.to_string(delimiter: "")
# UUID16 = TLV type 06, length 42
["0642", int_to_string(presentation, 2), decimalized_uuid]
end
defp int_to_string(value, num_digits) when value >= 0 do
value
|> Integer.to_string(10)
|> String.pad_leading(num_digits, "0")
end
end