bacnet_objects/trend/references.rs
1//! Log_DeviceObjectProperty on both trend objects (#1234): a Trend Log holds
2//! one `BACnetDeviceObjectPropertyReference` (Clause 12.25.8), a Trend Log
3//! Multiple a BACnetARRAY of them (Clause 12.30.11). Both serve the shared
4//! Clause 21 encoding and take network writes through the checks here.
5
6use bacnet_types::constructed::BACnetDeviceObjectPropertyReference;
7use bacnet_types::enums::{ErrorClass, ErrorCode, ObjectType};
8use bacnet_types::error::Error;
9
10use crate::common;
11use crate::device_reference::{check_device_member, check_local_member};
12
13/// The most references a Trend Log Multiple holds. Each poll reads every
14/// one and each record carries a value per reference, so the array is
15/// bounded locally; a longer one is RESOURCES / NO_SPACE_TO_WRITE_PROPERTY.
16pub const MAX_LOG_DEVICE_OBJECT_PROPERTIES: usize = 64;
17
18/// RESOURCES / NO_SPACE_TO_WRITE_PROPERTY, for a Trend Log Multiple array
19/// past [`MAX_LOG_DEVICE_OBJECT_PROPERTIES`].
20pub(super) fn no_space_error() -> Error {
21 common::protocol_error(ErrorClass::RESOURCES, ErrorCode::NO_SPACE_TO_WRITE_PROPERTY)
22}
23
24/// The element a write of index 0 appends when it lengthens a Trend Log
25/// Multiple's array: the shared unset form, Analog Input 4194303's
26/// Present_Value, an empty element under Clause 12.30.11, so the poller logs
27/// NO_PROPERTY_SPECIFIED for it. A Trend Log without a reference reads as the
28/// same reference (#1417).
29pub(super) fn empty_element() -> BACnetDeviceObjectPropertyReference {
30 crate::device_reference::unset_reference(ObjectType::ANALOG_INPUT)
31}
32
33/// Check a reference a client writes with the shared
34/// [`check_local_member`]: a Device member that isn't a Device identifier is
35/// PROPERTY / VALUE_OUT_OF_RANGE, and any other Device member PROPERTY /
36/// OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED, since the poller reads only its own
37/// database, which both clauses let a writable reference be held to. The
38/// bundled server has already put one naming its own Device in local form.
39/// An unset reference, its object or Device instance 4194303, names nothing
40/// (Clause 12.30.11 for a Trend Log Multiple element), so a Device member
41/// there is kept as written.
42pub(super) fn check_written(reference: &BACnetDeviceObjectPropertyReference) -> Result<(), Error> {
43 check_device_member(reference.device_identifier)?;
44 if reference.is_unset() {
45 return Ok(());
46 }
47 check_local_member(reference.device_identifier)
48}