In bacpypes3, DailySchedule, TimeValue, and AnyAtomic are Python implementations of the BACnet construct types defined in ASHRAE 135. DailySchedule and TimeValue live in the library's bacpypes3.basetypes module; AnyAtomic lives in bacpypes3.constructeddata. The canonical source is the bacpypes3 repository linked from its PyPI project page. A Schedule object's Weekly_Schedule is an array of seven DailySchedule entries; each DailySchedule carries a sequence of TimeValue entries; each TimeValue pairs a BACnet Time with an AnyAtomic value (Boolean, Unsigned, Real, Enumerated, etc.). Most of the type errors builders hit come from passing a raw Python value where a BACnet primitive (or an AnyAtomic wrapping one) is required.
Scenario: Building a Schedule Object in bacpypes3
You are writing a Python service against bacpypes3 — a custom application, a test harness, or a small supervisor — and you need to either build a BACnet Schedule object locally or write a new Weekly_Schedule to a remote device. The BACnet spec describes the structure in plain English, but as soon as you try to instantiate the Python classes, you get errors that look like:
TypeErroronTimeValue(...)because thevalueargument is a bare Pythonfloatorboolinstead of a BACnet primitive.- An
AnyAtomic-related error when you try to nest a non-atomic type (a structured object) inside aTimeValue. - A peer device rejects the WriteProperty with invalid-data-type after the encode succeeds locally.
The fix is almost always a type-correctness problem, not a bug in bacpypes3. To resolve it cleanly, it helps to read the actual class definitions in the source — which is what the search query that brought most readers here is really asking for.
The ASHRAE 135 Types Behind the Python Classes
The bacpypes3 classes are direct Python translations of the constructed and primitive types defined in ASHRAE Standard 135. Treat the spec as the source of truth for shape and constraints, and the Python library as the encoder/decoder.
- Schedule object — defined in the Schedule object type clause of ASHRAE 135. Its
Weekly_Scheduleproperty is an array of sevenDailyScheduleentries. Element 1 corresponds to Monday, element 7 to Sunday. (BACnet arrays are 1-indexed in the protocol; the Python library may expose them as a 0-indexed list — verify against the bacpypes3 source before assuming.) - DailySchedule — a constructed type containing one tagged element,
day-schedule, which is itself a list ofTimeValueentries in ascending time order. An empty list is valid and means "no scheduled changes that day"; the schedule simply holds whatever value was active when the day began (theSchedule_Defaultat midnight on the first day). - TimeValue — a SEQUENCE of two fields:
time(a BACnetTimeprimitive) andvalue(typed asAnyAtomic). Each entry says "at this time of day, the scheduled value becomes this." - AnyAtomic — a restricted CHOICE that accepts only atomic primitives:
Null,Boolean,Unsigned,Integer,Real,Double,OctetString,CharacterString,BitString,Enumerated,Date,Time. You cannot put a structured type (an Object Identifier reference, a SEQUENCE) inside aTimeValue; the schedule mechanism is designed to drive a single atomic property likePresent_Value.
The schedule's List_Of_Object_Property_References property is what determines which atomic property on which device gets written when a TimeValue fires. The AnyAtomic in the TimeValue must be type-compatible with that target property — sending a Boolean to a Real-typed Present_Value is a common cause of post-write rejection.
Where the Source Lives
bacpypes3 is the Python 3 / asyncio-based rewrite of the original bacpypes library. The authoritative places to look for the type definitions:
- PyPI project page — pypi.org/project/bacpypes3/. The page links to the project's homepage / source repository for the currently published release. Always cross-check version numbers here before quoting an API shape.
- Installed package — the fastest way to read the real definitions is to look at the installed code. After
pip install bacpypes3, the base types are in thebacpypes3.basetypesmodule of your site-packages — search there forDailyScheduleandTimeValue.AnyAtomicis defined one module over, inbacpypes3.constructeddata. - Project documentation — the library's README and any Read the Docs build linked from PyPI document the import paths and constructor signatures for the version you have installed. Constructor signatures have evolved across bacpypes3 releases, so prefer the docs that match your installed version over older tutorials.
- ASHRAE 135 — for the protocol-level definitions of Schedule, DailySchedule, TimeValue, and AnyAtomic, the standard itself is normative. The bacpypes3 source intentionally mirrors the spec's structure, so if a Python class and the spec disagree, the spec wins for interoperability.
Constructing a Weekly_Schedule Without Type Errors
The pattern that works across recent bacpypes3 releases:
- Build BACnet primitives, not Python primitives. Wrap your scheduled value in the matching bacpypes3 primitive class (
Real,Boolean,Unsigned,Enumerated) before constructing theTimeValue. The exact constructor forAnyAtomic— whether it auto-coerces a primitive or requires an explicit cast — varies by version; consult the installed source. - Use the BACnet Time type for the time field. Pass a
bacpypes3.primitivedata.Time(or whatever path the installed version exposes), not adatetime.time. Hours run 0–23, minutes and seconds 0–59, and hundredths can be wildcarded with0xFFper ASHRAE 135 if you want "unspecified." - Keep TimeValue entries in ascending time order within each DailySchedule. The standard requires it, and several BAS supervisors will silently re-sort or reject lists that arrive out of order.
- Make sure all seven days are present.
Weekly_Scheduleis a fixed array of seven DailySchedules, one per day. An emptyDailyScheduleis fine for "no transitions today," but you cannot omit the day entirely. - Verify the type match against the target. If your schedule drives a Real-typed point, every
TimeValue.valuemust be a Real (wrapped appropriately). Mixing types within a single schedule is legal in the spec but is rejected by many controllers in practice.
Common Pitfalls
- Passing a raw Python
boolorfloatas the value. bacpypes3 needs to know which BACnet primitive to encode. Wrap explicitly —Boolean(True),Real(72.0),Unsigned(3)— rather than relying on coercion. - Using a structured type inside TimeValue.
AnyAtomicis restricted to atomic primitives. ObjectIdentifier, BACnetAddress, and any constructed SEQUENCE will not encode here. If you need to switch a setpoint and a mode together, use two coordinated schedules, not one with a complex value. - Off-by-one on the day index. ASHRAE 135 specifies Monday as element 1 of
Weekly_Schedule, but Python lists are 0-indexed. Decide which convention your code uses and document it; never mix them in one codebase. - Quoting an old constructor signature. bacpypes3 has gone through several API revisions during its asyncio rewrite. A Stack Overflow answer from an older release may show keyword arguments that no longer exist. The installed source under site-packages is always definitive for your environment.
- Confusing bacpypes3 with the legacy bacpypes. The original
bacpypes(Python 2/3, no asyncio) andbacpypes3(Python 3, asyncio-native) are separate packages with overlapping class names but different import paths and constructors. Make sure yourpip listshows the one you intended.
When to Escalate
If the types match the spec and a peer device still rejects the schedule, the problem is usually on the remote side: a controller that does not fully implement Schedule object writes, a vendor-specific restriction on which atomic types are accepted, or a missing Out_Of_Service handling. Escalate by:
- Capturing the WriteProperty and the reject/error response in Wireshark and identifying the BACnet error class and code in the reply.
- Reading the controller's BACnet Protocol Implementation Conformance Statement (PICS) to confirm Schedule object writes are supported and which atomic value types it accepts.
- Filing an issue on the bacpypes3 repository (linked from the PyPI page) only after you have ruled out a peer-side limitation — include a minimal reproducible example with the library version pinned.
Related KB Entries
- BACpypes3: Custom BACnet Applications in Python — broader walkthrough of building applications on bacpypes3 beyond Schedule objects.
- Python BACnet Scripting with BAC0 — if you only need to read or write existing schedules and don't require low-level type control, BAC0's higher-level API is often the faster path.
Source Attribution
- bacpypes3 on PyPI — the canonical project page; links to the source repository for the currently published release.
- ASHRAE Standard 135 — BACnet, A Data Communication Protocol for Building Automation and Control Networks. Normative reference for the Schedule object, DailySchedule, TimeValue, and AnyAtomic construct types.
- ASHRAE 135 standard listing — where to obtain the current published version of the BACnet standard.
Additional testing and field validation by SiteConduit.
Was this article helpful?
Related Articles
Why bacpypes3 Defines class TimeValue(Sequence)
Tools & Librariesbacpypes3 class Any: The Open BACnet Value Container
Tools & Librariesbacpypes3 Time Class: Why It's a Tuple of (Hour, Minute, Second, Hundredth)
Niagara / TridiumTridium Upgrade: Niagara Version Upgrade and Migration Guide
Need to do this remotely? SiteConduit provides Layer 2 access that preserves BACnet broadcasts — no BBMD needed for remote sessions. Join the waitlist.
SiteConduit Technical Team
Idea Networks Inc.
SiteConduit builds managed remote access for building automation. Our knowledge base is maintained by BAS professionals with hands-on experience deploying and troubleshooting BACnet, Niagara, Modbus, and Facility Explorer systems.