@@ -69,6 +69,56 @@ uint32_t button_time_stamp = 0; // debouncing control
6969bool button_state = false ; // false = released | true = pressed
7070const uint32_t decommissioningTimeout = 5000 ; // keep the button pressed for 5s, or longer, to decommission
7171
72+ // Simulated Occupancy Sensor with HoldTime support
73+ // When occupancy is detected, it holds the "occupied" state for HoldTime seconds
74+ // After HoldTime expires, it automatically switches to "unoccupied"
75+ //
76+ // Behavior for different HoldTime vs detectionInterval relationships:
77+ // - holdTime_ms < detectionInterval: State switches to unoccupied after HoldTime, then waits for next detection
78+ // - holdTime_ms == detectionInterval: If detections keep coming, timer resets (continuous occupancy)
79+ // - holdTime_ms > detectionInterval: If detections keep coming, timer resets (continuous occupancy)
80+ // If detections stop, HoldTime expires after the last detection
81+ bool simulatedHWOccupancySensor () {
82+ static bool occupancyState = false ;
83+ static uint32_t lastDetectionTime = 0 ;
84+ static uint32_t lastDetectionEvent = millis ();
85+ const uint32_t detectionInterval = 120000 ; // Simulate detection every 2 minutes
86+
87+ // Get current HoldTime from the sensor (can be changed by Matter Controller)
88+ uint32_t holdTime_ms = OccupancySensor.getHoldTime () * 1000 ; // Convert seconds to milliseconds
89+
90+ // Check HoldTime expiration FIRST (before processing new detections)
91+ // This ensures HoldTime can expire even if a detection occurs in the same iteration
92+ if (occupancyState && (millis () - lastDetectionTime > holdTime_ms)) {
93+ occupancyState = false ;
94+ // Reset detection interval counter so next detection can happen immediately
95+ // This makes the simulation more responsive after the room becomes unoccupied
96+ lastDetectionEvent = millis ();
97+ Serial.println (" HoldTime expired. Switching to unoccupied state." );
98+ }
99+
100+ // Simulate periodic occupancy detection (e.g., motion detected)
101+ // Check this AFTER HoldTime expiration so new detections can immediately re-trigger occupancy
102+ if (millis () - lastDetectionEvent > detectionInterval) {
103+ // New detection event occurred
104+ lastDetectionEvent = millis ();
105+
106+ if (!occupancyState) {
107+ // Transition from unoccupied to occupied - start hold timer
108+ occupancyState = true ;
109+ lastDetectionTime = millis ();
110+ Serial.printf (" Occupancy detected! Holding state for %u seconds (HoldTime)\n " , OccupancySensor.getHoldTime ());
111+ } else {
112+ // Already occupied - new detection extends the hold period by resetting the timer
113+ // This simulates continuous occupancy (person still present)
114+ lastDetectionTime = millis ();
115+ Serial.printf (" Occupancy still detected. Resetting hold timer to %u seconds (HoldTime)\n " , OccupancySensor.getHoldTime ());
116+ }
117+ }
118+
119+ return occupancyState;
120+ }
121+
72122void setup () {
73123 // Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node
74124 pinMode (buttonPin, INPUT_PULLUP);
@@ -154,57 +204,6 @@ void setup() {
154204 }
155205}
156206
157- // Simulated Occupancy Sensor with HoldTime support
158- // When occupancy is detected, it holds the "occupied" state for HoldTime seconds
159- // After HoldTime expires, it automatically switches to "unoccupied"
160- //
161- // Behavior for different HoldTime vs detectionInterval relationships:
162- // - holdTime_ms < detectionInterval: State switches to unoccupied after HoldTime, then waits for next detection
163- // - holdTime_ms == detectionInterval: If detections keep coming, timer resets (continuous occupancy)
164- // - holdTime_ms > detectionInterval: If detections keep coming, timer resets (continuous occupancy)
165- // If detections stop, HoldTime expires after the last detection
166- bool simulatedHWOccupancySensor () {
167-
168- static bool occupancyState = false ;
169- static uint32_t lastDetectionTime = 0 ;
170- static uint32_t lastDetectionEvent = millis ();
171- const uint32_t detectionInterval = 120000 ; // Simulate detection every 2 minutes
172-
173- // Get current HoldTime from the sensor (can be changed by Matter Controller)
174- uint32_t holdTime_ms = OccupancySensor.getHoldTime () * 1000 ; // Convert seconds to milliseconds
175-
176- // Check HoldTime expiration FIRST (before processing new detections)
177- // This ensures HoldTime can expire even if a detection occurs in the same iteration
178- if (occupancyState && (millis () - lastDetectionTime > holdTime_ms)) {
179- occupancyState = false ;
180- // Reset detection interval counter so next detection can happen immediately
181- // This makes the simulation more responsive after the room becomes unoccupied
182- lastDetectionEvent = millis ();
183- Serial.println (" HoldTime expired. Switching to unoccupied state." );
184- }
185-
186- // Simulate periodic occupancy detection (e.g., motion detected)
187- // Check this AFTER HoldTime expiration so new detections can immediately re-trigger occupancy
188- if (millis () - lastDetectionEvent > detectionInterval) {
189- // New detection event occurred
190- lastDetectionEvent = millis ();
191-
192- if (!occupancyState) {
193- // Transition from unoccupied to occupied - start hold timer
194- occupancyState = true ;
195- lastDetectionTime = millis ();
196- Serial.printf (" Occupancy detected! Holding state for %u seconds (HoldTime)\n " , OccupancySensor.getHoldTime ());
197- } else {
198- // Already occupied - new detection extends the hold period by resetting the timer
199- // This simulates continuous occupancy (person still present)
200- lastDetectionTime = millis ();
201- Serial.printf (" Occupancy still detected. Resetting hold timer to %u seconds (HoldTime)\n " , OccupancySensor.getHoldTime ());
202- }
203- }
204-
205- return occupancyState;
206- }
207-
208207void loop () {
209208 // Check if the button has been pressed
210209 if (digitalRead (buttonPin) == LOW && !button_state) {
0 commit comments