Source code for BAC0.core.functions.TimeSync

# -*- coding: utf-8 -*-
# Copyright (C) 2015 by Christian Tremblay, P.Eng <>
# Licensed under LGPLv3, see file LICENSE in this source tree.
""" - creation of time synch requests

# --- standard Python modules ---
import datetime as dt
from datetime import datetime

import pytz
from bacpypes.apdu import TimeSynchronizationRequest, UTCTimeSynchronizationRequest
from bacpypes.basetypes import DateTime
from bacpypes.core import deferred
from bacpypes.iocb import IOCB

# --- 3rd party modules ---
from bacpypes.pdu import Address, GlobalBroadcast, LocalBroadcast
from bacpypes.primitivedata import Date, Time

from ...core.utils.notes import note_and_log
from import (

def _build_datetime(UTC=False):
    if UTC:
        _d = dt.datetime.utcnow().date()
        _t = dt.datetime.utcnow().time()
        _date = Date(
            year=_d.year - 1900, month=_d.month,, day_of_week=_d.isoweekday()
        _time = Time(
            hundredth=int(_t.microsecond / 10000),
        _date = Date().now().value
        _time = Time().now().value
    return DateTime(date=_date, time=_time)

[docs]@note_and_log class TimeSync: """ Mixin to support Time Synchronisation from BAC0 to other devices """
[docs] def time_sync(self, destination=None, datetime=None, UTC=False): """ Take local time and send it to devices. User can also provide a datetime value (constructed following bacpypes.basetypes.Datetime format). To create a DateTime :: from bacpypes.basetypes import DateTime from bacpypes.primitivedata import Date, Time # Create date and time _date = Date('2019-08-05') _time = Time('16:45') # Create Datetime _datetime = DateTime(date=_date.value, time=_time.value) # Pass this to the function bacnet.time_sync(datetime=_datetime) """ if not self._started: raise ApplicationNotStarted("BACnet stack not running - use startApp()") if not datetime: _datetime = _build_datetime(UTC=UTC) elif isinstance(datetime, DateTime): _datetime = datetime else: raise ValueError( "Please provide valid DateTime in bacpypes.basetypes.DateTime format" ) # build a request if UTC: request = UTCTimeSynchronizationRequest(time=_datetime) else: request = TimeSynchronizationRequest(time=_datetime) if destination: if destination.lower() == "global": request.pduDestination = GlobalBroadcast() elif destination.lower() == "local": request.pduDestination = LocalBroadcast() else: try: request.pduDestination = Address(destination) except (TypeError, ValueError): self._log.warning( "Destination unrecognized ({}), setting local broadcast".format( destination ) ) request.pduDestination = LocalBroadcast() else: request.pduDestination = LocalBroadcast() self._log.debug("{:>12} {}".format("- request:", request)) iocb = IOCB(request) # make an IOCB # pass to the BACnet stack deferred(self.this_application.request_io, iocb) # Unconfirmed wait until complete iocb.wait() # Wait for BACnet response year, month, day, dow = year = year + 1900 hour, minutes, sec, msec = _datetime.time d = dt.datetime(year, month, day, hour, minutes, sec, msec)"Time Sync Request sent to network : {}".format(d.isoformat()))
[docs]class TimeHandler(object): """ This class will deal with Time / Timezone related features To deal with DateTime Value correctly we need to be aware of timezone. """ def __init__(self, tz: str = "America/Montreal") -> None: self.set_timezone(tz)
[docs] def set_timezone(self, tz: str) -> None: self.timezone = pytz.timezone(tz)
@property def now(self) -> datetime: return
[docs] def local_time(self): return
[docs] def local_date(self): return
[docs] def utcOffset(self) -> float: "Returns UTC offset in minutes" return round( / 60) # type: ignore[union-attr]
[docs] def is_dst(self) -> bool: return self.timezone.dst( != dt.timedelta(0)
def __repr__(self): return "{}".format(self.__dict__)