Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / examples / lock-app / cc13x2x7_26x2x7 / main / BoltLockManager.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2019 Google LLC.
5  *    All rights reserved.
6  *
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
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  */
19
20 #include "BoltLockManager.h"
21
22 #include "AppConfig.h"
23 #include "AppTask.h"
24 #include "FreeRTOS.h"
25
26 #define ACTUATOR_MOVEMENT_PERIOS_MS 500
27
28 BoltLockManager BoltLockManager::sLock;
29
30 int BoltLockManager::Init()
31 {
32     int ret = 0;
33
34     mTimerHandle = xTimerCreate("BLT_TIMER", pdMS_TO_TICKS(ACTUATOR_MOVEMENT_PERIOS_MS), pdFALSE, this, TimerEventHandler);
35     if (NULL == mTimerHandle)
36     {
37         PLAT_LOG("failed to create bolt lock timer");
38         while (1)
39             ;
40     }
41
42     mState              = kState_LockingCompleted;
43     mAutoLockTimerArmed = false;
44     mAutoRelock         = false;
45     mAutoLockDuration   = 0;
46
47     return ret;
48 }
49
50 void BoltLockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
51 {
52     mActionInitiated_CB = aActionInitiated_CB;
53     mActionCompleted_CB = aActionCompleted_CB;
54 }
55
56 bool BoltLockManager::IsActionInProgress()
57 {
58     return (mState == kState_LockingInitiated || mState == kState_UnlockingInitiated);
59 }
60
61 bool BoltLockManager::IsUnlocked()
62 {
63     return (mState == kState_UnlockingCompleted);
64 }
65
66 void BoltLockManager::EnableAutoRelock(bool aOn)
67 {
68     mAutoRelock = aOn;
69 }
70
71 void BoltLockManager::SetAutoLockDuration(uint32_t aDurationInSecs)
72 {
73     mAutoLockDuration = aDurationInSecs;
74 }
75
76 bool BoltLockManager::InitiateAction(int32_t aActor, Action_t aAction)
77 {
78     bool action_initiated = false;
79     State_t new_state;
80
81     // Initiate Lock/Unlock Action only when the previous one is complete.
82     if (mState == kState_LockingCompleted && aAction == UNLOCK_ACTION)
83     {
84         action_initiated = true;
85
86         new_state = kState_UnlockingInitiated;
87     }
88     else if (mState == kState_UnlockingCompleted && aAction == LOCK_ACTION)
89     {
90         action_initiated = true;
91
92         new_state = kState_LockingInitiated;
93     }
94
95     if (action_initiated)
96     {
97         if (mAutoLockTimerArmed && new_state == kState_LockingInitiated)
98         {
99             // If auto lock timer has been armed and someone initiates locking,
100             // cancel the timer and continue as normal.
101             mAutoLockTimerArmed = false;
102
103             CancelTimer();
104         }
105
106         StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
107
108         // Since the timer started successfully, update the state and trigger callback
109         mState = new_state;
110
111         if (mActionInitiated_CB)
112         {
113             mActionInitiated_CB(aAction, aActor);
114         }
115     }
116
117     return action_initiated;
118 }
119
120 void BoltLockManager::StartTimer(uint32_t aTimeoutMs)
121 {
122     xTimerChangePeriod(mTimerHandle, pdMS_TO_TICKS(aTimeoutMs), 100);
123     xTimerStart(mTimerHandle, 100);
124 }
125
126 void BoltLockManager::CancelTimer(void)
127 {
128     xTimerStop(mTimerHandle, 100);
129 }
130
131 void BoltLockManager::TimerEventHandler(TimerHandle_t aTimer)
132 {
133     BoltLockManager * lock = static_cast<BoltLockManager *>(pvTimerGetTimerID(aTimer));
134
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.
138     AppEvent event;
139     event.Type                  = AppEvent::kEventType_AppEvent;
140     event.BoltLockEvent.Context = static_cast<BoltLockManager *>(lock);
141     if (lock->mAutoLockTimerArmed)
142     {
143         event.Handler = AutoReLockTimerEventHandler;
144     }
145     else
146     {
147         event.Handler = ActuatorMovementTimerEventHandler;
148     }
149     GetAppTask().PostEvent(&event);
150 }
151
152 void BoltLockManager::AutoReLockTimerEventHandler(AppEvent * aEvent)
153 {
154     BoltLockManager * lock = static_cast<BoltLockManager *>(aEvent->BoltLockEvent.Context);
155     int32_t actor          = 0;
156
157     // Make sure auto lock timer is still armed.
158     if (!lock->mAutoLockTimerArmed)
159     {
160         return;
161     }
162
163     lock->mAutoLockTimerArmed = false;
164
165     PLAT_LOG("Auto Re-Lock has been triggered!");
166
167     lock->InitiateAction(actor, LOCK_ACTION);
168 }
169
170 void BoltLockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
171 {
172     Action_t actionCompleted = INVALID_ACTION;
173
174     BoltLockManager * lock = static_cast<BoltLockManager *>(aEvent->BoltLockEvent.Context);
175
176     if (lock->mState == kState_LockingInitiated)
177     {
178         lock->mState    = kState_LockingCompleted;
179         actionCompleted = LOCK_ACTION;
180     }
181     else if (lock->mState == kState_UnlockingInitiated)
182     {
183         lock->mState    = kState_UnlockingCompleted;
184         actionCompleted = UNLOCK_ACTION;
185     }
186
187     if (actionCompleted != INVALID_ACTION)
188     {
189         if (lock->mActionCompleted_CB)
190         {
191             lock->mActionCompleted_CB(actionCompleted);
192         }
193
194         if (lock->mAutoRelock && actionCompleted == UNLOCK_ACTION)
195         {
196             // Start the timer for auto relock
197             lock->StartTimer(lock->mAutoLockDuration * 1000);
198
199             lock->mAutoLockTimerArmed = true;
200
201             PLAT_LOG("Auto Re-lock enabled. Will be triggered in %u seconds", lock->mAutoLockDuration);
202         }
203     }
204 }