#!/usr/bin/python# -*- coding: utf-8 -*-## Copyright (C) 2015 by Christian Tremblay, P.Eng <christian.tremblay@servisys.com># Licensed under LGPLv3, see file LICENSE in this source tree.#"""TimeSync.py - creation of time synch requests"""importdatetimeasdtimporttypingastfromdatetimeimportdatetime# --- standard Python modules ---importpytzfrombacpypes3.apduimportTimeSynchronizationRequest,UTCTimeSynchronizationRequestfrombacpypes3.appimportApplicationfrombacpypes3.basetypesimportDateTime# --- 3rd party modules ---frombacpypes3.pduimportAddress,GlobalBroadcast,LocalBroadcastfrombacpypes3.primitivedataimportDate,TimefromBAC0.core.app.asyncAppimportBAC0Applicationfrom...core.utils.notesimportnote_and_logfrom..io.IOExceptionsimportApplicationNotStarteddef_build_datetime(UTC=False):ifUTC:_d=dt.datetime.utcnow().date()_t=dt.datetime.utcnow().time()_date=Date((_d.year-1900,_d.month,_d.day,_d.isoweekday()))_time=Time((_t.hour,_t.minute,_t.second,int(_t.microsecond/10000),))else:_date=Date().now()_time=Time().now()returnDateTime(date=_date,time=_time)
[docs]@note_and_logclassTimeSync:""" Mixin to support Time Synchronisation from BAC0 to other devices """
[docs]deftime_sync(self,destination:t.Optional[str]=None,datetime:t.Optional[DateTime]=None,UTC:bool=False)->None:""" 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) """ifnotself._started:raiseApplicationNotStarted("BACnet stack not running - use startApp()")_this_application:BAC0Application=self.this_application_app:Application=_this_application.appifnotdatetime:_datetime=_build_datetime(UTC=UTC)elifisinstance(datetime,DateTime):_datetime=datetimeelse:raiseValueError("Please provide valid DateTime in bacpypes.basetypes.DateTime format")# build a requestifUTC:request=UTCTimeSynchronizationRequest(time=_datetime)else:request=TimeSynchronizationRequest(time=_datetime)ifdestination:ifdestination.lower()=="global":request.pduDestination=GlobalBroadcast()elifdestination.lower()=="local":request.pduDestination=LocalBroadcast()else:try:request.pduDestination=Address(destination)except(TypeError,ValueError):self.log("Destination unrecognized ({destination}), setting local broadcast",level="warning",)request.pduDestination=LocalBroadcast()else:request.pduDestination=LocalBroadcast()self.log(f"{'- request:':>12}{request}",level="debug")_app.request(request)year,month,day,dow=_datetime.dateyear=year+1900hour,minutes,sec,msec=_datetime.timed=dt.datetime(year,month,day,hour,minutes,sec,msec)self.log(f"Time Sync Request sent to network : {d.isoformat()}",level="info")
[docs]classTimeHandler(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]defutcOffset(self)->float:"Returns UTC offset in minutes"returnround(self.now.astimezone().utcoffset().total_seconds()/60)# type: ignore[union-attr]