BACnet.Protocol.BACnetTime (bacstack v0.1.0-dev.1)

Copy Markdown View Source

A BACnet Time is a structured value (application tag 11) that can represent either a specific time of day or a time pattern with one or more components marked as :unspecified. It is the natural companion to BACnet.Protocol.BACnetDate and appears in the same contexts: schedules, calendars, trend logs, event notifications, and TimeSynchronization services.

Each component (hour, minute, second, hundredth) may be a concrete integer or the atom :unspecified (encoded as 0xFF). A completely unspecified time is treated as "don't care".

BACnet Specification References

  • Encoding: ASHRAE 135-2012 Clause 20.2.13. Four contents octets: hour (0-23), minute, second, hundredths. 0xFF in any position means unspecified.
  • Restrictions (20.2.13): Neither an unspecified time nor a time pattern shall be used when conveying an actual time (e.g. the Device object's Local_Time property or a TimeSynchronization-Request).
  • ASN.1 (Clause 21): Time ::= [APPLICATION 11] OCTET STRING (SIZE(4)).
  • Primary usage: weekly_schedule / exception_schedule entries (via TimeValue), ReadRange time ranges, Event Timestamps, and many "last changed" time properties.

The helpers in this module correctly round-trip with Elixir Time while treating :unspecified components by substituting values from a reference time.

Examples

Specific time

iex> time = %BACnetTime{hour: 8, minute: 30, second: 0, hundredth: 0}
iex> BACnetTime.specific?(time)
true
iex> BACnetTime.to_time!(time)
~T[08:30:00]

Partial wildcard (e.g. "every day at 9:15")

iex> daily = %BACnetTime{hour: 9, minute: 15, second: :unspecified, hundredth: :unspecified}
iex> BACnetTime.specific?(daily)
false

Edge cases

All components unspecified resolves using the reference time:

iex> any_time = %BACnetTime{hour: :unspecified, minute: :unspecified, second: :unspecified, hundredth: :unspecified}
iex> BACnetTime.specific?(any_time)
false
iex> BACnetTime.to_time!(any_time, ~T[14:30:00])
~T[14:30:00]

Warning

Per the specification, unspecified times or time patterns shall not be used for actual time values such as the Device object's Local_Time.

See Also

Summary

Types

t()

Represents a BACnet Time (application tag 11).

Functions

Compares two BACnet Time.

Encodes the given BACnet Time into an application tag.

Converts a Time into a BACnet Time.

Parses a BACnet Time from BACnet application tags encoding.

Checks whether the given BACnet Time is a specific time value (every component is a numeric value).

Converts a BACnet Time into a Time.

Creates a new BACnet Time with the current UTC time.

Validates whether the given BACnet time is in form valid.

Types

t()

@type t() :: %BACnet.Protocol.BACnetTime{
  hour: 0..23 | :unspecified,
  hundredth: 0..99 | :unspecified,
  minute: 0..59 | :unspecified,
  second: 0..59 | :unspecified
}

Represents a BACnet Time (application tag 11).

  • hour - 0-23 or :unspecified
  • minute - 0-59 or :unspecified
  • second - 0-59 or :unspecified
  • hundredth - 0-99 (hundredths of a second) or :unspecified

Any component may be :unspecified, turning the value into a time pattern. specific?/1 returns false for any such pattern. See to_time/2 for how patterns are resolved against a reference time.

Functions

compare(time1, time2)

@spec compare(t(), t()) :: :gt | :eq | :lt

Compares two BACnet Time.

Returns :gt if first time is later than the second, and :lt for vice versa. If the two times are equal, :eq is returned.

Note that this is achieved by converting to Time and then comparing them.

encode(time, opts \\ [])

@spec encode(t(), Keyword.t()) ::
  {:ok, BACnet.Protocol.ApplicationTags.encoding_list()} | {:error, term()}

Encodes the given BACnet Time into an application tag.

from_time(time)

@spec from_time(Time.t()) :: t()

Converts a Time into a BACnet Time.

parse(tags)

Parses a BACnet Time from BACnet application tags encoding.

specific?(time)

@spec specific?(t()) :: boolean()

Checks whether the given BACnet Time is a specific time value (every component is a numeric value).

to_time(time, ref_time \\ Time.utc_now())

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

Converts a BACnet Time into a Time.

If any of the fields are unspecified, the reference time (current UTC value) is used.

to_time!(time, ref_time \\ Time.utc_now())

@spec to_time!(t(), Time.t()) :: Time.t() | no_return()

Bang-version of to_time/1.

utc_now()

@spec utc_now() :: t()

Creates a new BACnet Time with the current UTC time.

valid?(t)

@spec valid?(t()) :: boolean()

Validates whether the given BACnet time is in form valid.

It only validates the struct is valid as per type specification.