1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//! Occupancy_Count and Reliability of an Access Zone while Out_Of_Service is
//! TRUE (Clauses 12.32.9, 12.32.10 and 12.32.11, Table 12-37 footnote 1,
//! #1247).
//!
//! Footnote 1 of Table 12-37 marks these two rows, so a client can stand in
//! for the zone's counting and fault detection by writing them. The zone takes
//! WriteProperty and WritePropertyMultiple of either one only while
//! Out_Of_Service is TRUE; in service both are refused with
//! WRITE_ACCESS_DENIED, before the datatype is looked at. Out of service:
//!
//! - an Occupancy_Count write has to be an Unsigned, any value while
//! counting is on and only zero while it is off (VALUE_OUT_OF_RANGE
//! otherwise; see `zone_occupancy`); another datatype is INVALID_DATA_TYPE;
//! - a Reliability write has to be an Enumerated inside the BACnetReliability
//! production, its proprietary range included; another number is
//! VALUE_OUT_OF_RANGE and another datatype INVALID_DATA_TYPE.
//!
//! A refused write changes nothing.
//!
//! Out of service the two values stop following the zone's own process, so
//! the zone keeps that process's values to one side:
//!
//! - On the FALSE-to-TRUE edge it puts aside the Occupancy_Count and
//! Reliability it serves (`common::write_out_of_service_with_restore`).
//! - Meanwhile a count the application reports (`set_occupancy_count`)
//! replaces the count put aside, not the one served, and a Reliability it
//! works out (`set_reliability_internal`) is refused, as on the other
//! Reliability carriers.
//! - On the TRUE-to-FALSE edge both go back to the values put aside, so the
//! zone's own state is served again at once and the simulation is gone.
//! Clause 12.32.11 leaves the count after the return to service to the
//! implementation; this is the choice made here.
//!
//! How a simulated value reaches the rest of the device: Status_Flags reads
//! FAULT from the Reliability served, so a simulated fault sets it, and
//! Occupancy_State follows the count served, so a simulated count moves it
//! (12.32.10). An Adjust_Value write is kept but leaves the simulated count
//! alone. The CHANGE_OF_STATE algorithm watches the Occupancy_State and
//! Reliability served (#1305), so a simulated count can raise an offnormal
//! event and a simulated fault a FAULT one, as item (f) of 12.32.10 asks. The
//! zone has no Table 13-1 row, so neither sends a SubscribeCOV report.
//! Anything reading these properties sees the simulation as it would see the
//! zone.
use ;
use Error;
use PropertyValue;
use simulated_reliability;
use cratecommon;
/// The values a client can simulate on an Access Zone while Out_Of_Service is
/// TRUE.
pub