Binary Coded Decimal (BCD) encoding and decoding helpers for DL/T 645 protocols.
In DL/T 645, meter addresses, numeric values (energy, voltage, current, etc.), and timestamps are represented in BCD format, typically transmitted with the least significant byte first (little-endian byte order).
Summary
Functions
Checks if a slave address matches a target address.
Supports broadcast address AAAAAAAAAAAA, 999999999999, and per-nibble wildcard A.
Converts a single BCD byte (0x00..0x99) to an integer (0..99).
Decodes 6 BCD bytes (little-endian) into a 12-character address string.
Decodes a 6-byte BCD timestamp YYMMDDhhmmss (transmitted order: ss, mm, hh, DD, MM, YY).
Returns {:ok, %NaiveDateTime{}} or {:error, reason}.
Decodes a 5-byte BCD date-minute YYMMDDhhmm (transmitted order: mm, hh, DD, MM, YY).
Returns {:ok, %NaiveDateTime{}} with seconds set to 0.
Decodes a BCD binary into a float or integer representing a fixed-point decimal.
For example, with decimals: 2 and bytes <<0x45, 0x23, 0x01, 0x00>> (little-endian), returns 123.45.
Decodes a BCD binary into an integer.
By default, endianness: :little (least significant byte first).
Decodes a 3-byte BCD time hhmmss (transmitted order: ss, mm, hh).
Returns {:ok, %Time{}}.
Encodes a 12-digit meter address string into 6 BCD bytes (little-endian, low byte first).
Encodes a NaiveDateTime or DateTime struct into 6-byte BCD YYMMDDhhmmss (ss, mm, hh, DD, MM, YY).
Encodes a NaiveDateTime or DateTime struct into 5-byte BCD YYMMDDhhmm (mm, hh, DD, MM, YY).
Encodes a float or numeric value into a fixed-point BCD binary.
Encodes an integer into BCD binary with the specified byte size and endianness.
Encodes a Time into 3-byte BCD hhmmss (ss, mm, hh).
Converts an integer (0..99) to a single BCD byte.
Functions
Checks if a slave address matches a target address.
Supports broadcast address AAAAAAAAAAAA, 999999999999, and per-nibble wildcard A.
@spec bcd_to_int(byte()) :: 0..99
Converts a single BCD byte (0x00..0x99) to an integer (0..99).
Decodes 6 BCD bytes (little-endian) into a 12-character address string.
Examples
iex> ExDlt645.BCD.decode_address(<<0x12, 0x90, 0x78, 0x56, 0x34, 0x12>>)
"123456789012"
@spec decode_datetime(binary()) :: {:ok, NaiveDateTime.t()} | {:error, term()}
Decodes a 6-byte BCD timestamp YYMMDDhhmmss (transmitted order: ss, mm, hh, DD, MM, YY).
Returns {:ok, %NaiveDateTime{}} or {:error, reason}.
@spec decode_datetime_min(binary()) :: {:ok, NaiveDateTime.t()} | {:error, term()}
Decodes a 5-byte BCD date-minute YYMMDDhhmm (transmitted order: mm, hh, DD, MM, YY).
Returns {:ok, %NaiveDateTime{}} with seconds set to 0.
@spec decode_float(binary(), non_neg_integer(), :little | :big) :: float()
Decodes a BCD binary into a float or integer representing a fixed-point decimal.
For example, with decimals: 2 and bytes <<0x45, 0x23, 0x01, 0x00>> (little-endian), returns 123.45.
Decodes a BCD binary into an integer.
By default, endianness: :little (least significant byte first).
Decodes a 3-byte BCD time hhmmss (transmitted order: ss, mm, hh).
Returns {:ok, %Time{}}.
Encodes a 12-digit meter address string into 6 BCD bytes (little-endian, low byte first).
Examples
iex> ExDlt645.BCD.encode_address("123456789012")
<<0x12, 0x90, 0x78, 0x56, 0x34, 0x12>>
iex> ExDlt645.BCD.encode_address("AAAAAAAAAAAA")
<<0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA>>
@spec encode_datetime(NaiveDateTime.t() | DateTime.t()) :: binary()
Encodes a NaiveDateTime or DateTime struct into 6-byte BCD YYMMDDhhmmss (ss, mm, hh, DD, MM, YY).
@spec encode_datetime_min(NaiveDateTime.t() | DateTime.t()) :: binary()
Encodes a NaiveDateTime or DateTime struct into 5-byte BCD YYMMDDhhmm (mm, hh, DD, MM, YY).
@spec encode_float(number(), non_neg_integer(), non_neg_integer(), :little | :big) :: binary()
Encodes a float or numeric value into a fixed-point BCD binary.
@spec encode_integer(integer(), non_neg_integer(), :little | :big) :: binary()
Encodes an integer into BCD binary with the specified byte size and endianness.
Encodes a Time into 3-byte BCD hhmmss (ss, mm, hh).
@spec int_to_bcd(0..99) :: byte()
Converts an integer (0..99) to a single BCD byte.