3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2019 Google LLC.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 #include "BoltLockManager.h"
22 #include "AppConfig.h"
26 #define ACTUATOR_MOVEMENT_PERIOS_MS 500
28 BoltLockManager BoltLockManager::sLock;
30 int BoltLockManager::Init()
34 mTimerHandle = xTimerCreate("BLT_TIMER", pdMS_TO_TICKS(ACTUATOR_MOVEMENT_PERIOS_MS), pdFALSE, this, TimerEventHandler);
35 if (NULL == mTimerHandle)
37 PLAT_LOG("failed to create bolt lock timer");
42 mState = kState_LockingCompleted;
43 mAutoLockTimerArmed = false;
45 mAutoLockDuration = 0;
50 void BoltLockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
52 mActionInitiated_CB = aActionInitiated_CB;
53 mActionCompleted_CB = aActionCompleted_CB;
56 bool BoltLockManager::IsActionInProgress()
58 return (mState == kState_LockingInitiated || mState == kState_UnlockingInitiated);
61 bool BoltLockManager::IsUnlocked()
63 return (mState == kState_UnlockingCompleted);
66 void BoltLockManager::EnableAutoRelock(bool aOn)
71 void BoltLockManager::SetAutoLockDuration(uint32_t aDurationInSecs)
73 mAutoLockDuration = aDurationInSecs;
76 bool BoltLockManager::InitiateAction(int32_t aActor, Action_t aAction)
78 bool action_initiated = false;
81 // Initiate Lock/Unlock Action only when the previous one is complete.
82 if (mState == kState_LockingCompleted && aAction == UNLOCK_ACTION)
84 action_initiated = true;
86 new_state = kState_UnlockingInitiated;
88 else if (mState == kState_UnlockingCompleted && aAction == LOCK_ACTION)
90 action_initiated = true;
92 new_state = kState_LockingInitiated;
97 if (mAutoLockTimerArmed && new_state == kState_LockingInitiated)
99 // If auto lock timer has been armed and someone initiates locking,
100 // cancel the timer and continue as normal.
101 mAutoLockTimerArmed = false;
106 StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
108 // Since the timer started successfully, update the state and trigger callback
111 if (mActionInitiated_CB)
113 mActionInitiated_CB(aAction, aActor);
117 return action_initiated;
120 void BoltLockManager::StartTimer(uint32_t aTimeoutMs)
122 xTimerChangePeriod(mTimerHandle, pdMS_TO_TICKS(aTimeoutMs), 100);
123 xTimerStart(mTimerHandle, 100);
126 void BoltLockManager::CancelTimer(void)
128 xTimerStop(mTimerHandle, 100);
131 void BoltLockManager::TimerEventHandler(TimerHandle_t aTimer)
133 BoltLockManager * lock = static_cast<BoltLockManager *>(pvTimerGetTimerID(aTimer));
135 // The timer event handler will be called in the context of the timer task
136 // once sLockTimer expires. Post an event to apptask queue with the actual handler
137 // so that the event can be handled in the context of the apptask.
139 event.Type = AppEvent::kEventType_AppEvent;
140 event.BoltLockEvent.Context = static_cast<BoltLockManager *>(lock);
141 if (lock->mAutoLockTimerArmed)
143 event.Handler = AutoReLockTimerEventHandler;
147 event.Handler = ActuatorMovementTimerEventHandler;
149 GetAppTask().PostEvent(&event);
152 void BoltLockManager::AutoReLockTimerEventHandler(AppEvent * aEvent)
154 BoltLockManager * lock = static_cast<BoltLockManager *>(aEvent->BoltLockEvent.Context);
157 // Make sure auto lock timer is still armed.
158 if (!lock->mAutoLockTimerArmed)
163 lock->mAutoLockTimerArmed = false;
165 PLAT_LOG("Auto Re-Lock has been triggered!");
167 lock->InitiateAction(actor, LOCK_ACTION);
170 void BoltLockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
172 Action_t actionCompleted = INVALID_ACTION;
174 BoltLockManager * lock = static_cast<BoltLockManager *>(aEvent->BoltLockEvent.Context);
176 if (lock->mState == kState_LockingInitiated)
178 lock->mState = kState_LockingCompleted;
179 actionCompleted = LOCK_ACTION;
181 else if (lock->mState == kState_UnlockingInitiated)
183 lock->mState = kState_UnlockingCompleted;
184 actionCompleted = UNLOCK_ACTION;
187 if (actionCompleted != INVALID_ACTION)
189 if (lock->mActionCompleted_CB)
191 lock->mActionCompleted_CB(actionCompleted);
194 if (lock->mAutoRelock && actionCompleted == UNLOCK_ACTION)
196 // Start the timer for auto relock
197 lock->StartTimer(lock->mAutoLockDuration * 1000);
199 lock->mAutoLockTimerArmed = true;
201 PLAT_LOG("Auto Re-lock enabled. Will be triggered in %u seconds", lock->mAutoLockDuration);