ExDlt645.BCD (ex_dlt645 v0.1.0)

Copy Markdown View Source

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

address_match?(meter_addr, target_addr)

@spec address_match?(String.t(), String.t()) :: boolean()

Checks if a slave address matches a target address. Supports broadcast address AAAAAAAAAAAA, 999999999999, and per-nibble wildcard A.

bcd_to_int(byte)

@spec bcd_to_int(byte()) :: 0..99

Converts a single BCD byte (0x00..0x99) to an integer (0..99).

decode_address(bytes)

@spec decode_address(binary()) :: String.t()

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"

decode_datetime(arg1)

@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}.

decode_datetime_min(arg1)

@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.

decode_float(bytes, decimals, endianness \\ :little)

@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.

decode_integer(bytes, endianness \\ :little)

@spec decode_integer(binary(), :little | :big) :: integer()

Decodes a BCD binary into an integer. By default, endianness: :little (least significant byte first).

decode_time(arg1)

@spec decode_time(binary()) :: {:ok, Time.t()} | {:error, term()}

Decodes a 3-byte BCD time hhmmss (transmitted order: ss, mm, hh). Returns {:ok, %Time{}}.

encode_address(addr_str)

@spec encode_address(String.t()) :: binary()

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>>

encode_datetime(map)

@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).

encode_datetime_min(map)

@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).

encode_float(num, byte_count, decimals, endianness \\ :little)

@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.

encode_integer(val, byte_count, endianness \\ :little)

@spec encode_integer(integer(), non_neg_integer(), :little | :big) :: binary()

Encodes an integer into BCD binary with the specified byte size and endianness.

encode_time(time)

@spec encode_time(Time.t()) :: binary()

Encodes a Time into 3-byte BCD hhmmss (ss, mm, hh).

int_to_bcd(num)

@spec int_to_bcd(0..99) :: byte()

Converts an integer (0..99) to a single BCD byte.