Source code for BAC0.core.functions.Calendar

#!/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.
#
# --- standard Python modules ---
import datetime
import typing as t

from bacpypes3.apdu import WritePropertyRequest
from bacpypes3.app import Application
from bacpypes3.basetypes import CalendarEntry, DateRange
from bacpypes3.constructeddata import Any, ArrayOf

# --- 3rd party modules ---
from bacpypes3.pdu import Address

from ...core.app.asyncApp import BAC0Application
from ...core.utils.notes import note_and_log


[docs] @note_and_log class Calendar: """ Everything you need to write dates and date ranges to a calendar object. """ DateList = ArrayOf(CalendarEntry) datelist_example = { "dates": [ {"date": "2021/3/14", "recurring": False}, {"date": "2021/3/10", "recurring": True}, ], "dateRanges": [ {"startDate": "2021/3/16", "endDate": "2021/3/21"}, {"startDate": "2021/3/5", "endDate": "2021/3/7"}, ], }
[docs] def create_calendar(self, dict_calendar): """ From a structured dict (see dateList_example), create a DateList an ArrayOf(CalendarEntry) """ entries = [] if "dates" in dict_calendar.keys(): for date_entry in dict_calendar["dates"]: year, month, day = (int(x) for x in date_entry["date"].split("/")) if date_entry["recurring"]: weekday = 255 else: weekday = datetime.date(year, month, day).weekday() + 1 if weekday > 7: weekday = 1 _date = (year - 1900, month, day, weekday) entries.append(CalendarEntry(date=_date)) if "dateRanges" in dict_calendar.keys(): for date_range_entry in dict_calendar["dateRanges"]: year, month, day = ( int(x) for x in date_range_entry["startDate"].split("/") ) weekday = datetime.date(year, month, day).weekday() + 1 if weekday > 7: weekday = 1 start_date = (year - 1900, month, day, weekday) year, month, day = ( int(x) for x in date_range_entry["endDate"].split("/") ) weekday = datetime.date(year, month, day).weekday() + 1 if weekday > 7: weekday = 1 end_date = (year - 1900, month, day, weekday) date_range = DateRange(startDate=start_date, endDate=end_date) entries.append(CalendarEntry(dateRange=date_range)) dateList = self.DateList(entries) return dateList
[docs] def make_calendar_request(self, destination, object_instance, dateList): request = WritePropertyRequest( objectIdentifier=("calendar", object_instance), propertyIdentifier="dateList", ) address = Address(destination) request.pduDestination = address request.propertyValue = Any(None) request.propertyValue.cast_in(dateList) return request
[docs] def send_calendar_request(self, request, timeout=10): _this_application: BAC0Application = self.this_application _app: Application = _this_application.app self.log(f"{'- request:':>12} {request}", level="debug") _app.request(request) self._log.info( f"Calendar Write request sent to device : {request.pduDestination}" )
[docs] def write_calendar_dateList(self, destination, calendar_instance, dates): calendar = self.create_calendar(dates) request = self.make_calendar_request( destination=destination, object_instance=calendar_instance, dateList=calendar, ) self.send_calendar_request(request)
[docs] async def read_calendar_dateList(self, address, calendar_instance): """ This function will read the dateList property of given calendar object and pass it to decode_dateList() to convert it into a human readable dict. """ try: dateList_object = await self.read( f"{address} calendar {calendar_instance} dateList" ) dict_calendar = self.decode_dateList(dateList_object) except Exception as error: self.log(f"exception: {error!r}", level="error") return {} return dict_calendar
[docs] def decode_dateList(self, dateList_object) -> t.Dict[str, t.List[t.Dict]]: dict_calendar = {"dates": [], "dateRanges": []} for entry in dateList_object: entry_dict: t.Dict[str, t.Union[str, bool]] = {} if entry.date: if entry.date[3] == 255: recurring = True else: recurring = False entry_dict["date"] = "{}/{}/{}".format( entry.date[0] + 1900, entry.date[1], entry.date[2] ) entry_dict["recurring"] = recurring dict_calendar["dates"].append(entry_dict) elif entry.dateRange: entry_dict["startDate"] = "{}/{}/{}".format( entry.dateRange.startDate[0] + 1900, entry.dateRange.startDate[1], entry.dateRange.startDate[2], ) entry_dict["endDate"] = "{}/{}/{}".format( entry.dateRange.endDate[0] + 1900, entry.dateRange.endDate[1], entry.dateRange.endDate[2], ) dict_calendar["dateRanges"].append(entry_dict) return dict_calendar