BoltLockManager.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. *
  3. * Copyright (c) 2020 Project CHIP Authors
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #include "BoltLockManager.h"
  18. #include "AppConfig.h"
  19. #include "AppTask.h"
  20. #include "esp_log.h"
  21. #include <freertos/FreeRTOS.h>
  22. static const char * TAG = "BoltLockManager";
  23. BoltLockManager BoltLockManager::sLock;
  24. TimerHandle_t sLockTimer;
  25. CHIP_ERROR BoltLockManager::Init()
  26. {
  27. // Create FreeRTOS sw timer for lock timer.
  28. sLockTimer = xTimerCreate("lockTmr", // Just a text name, not used by the RTOS kernel
  29. 1, // == default timer period (mS)
  30. false, // no timer reload (==one-shot)
  31. (void *) this, // init timer id = lock obj context
  32. TimerEventHandler // timer callback handler
  33. );
  34. if (sLockTimer == NULL)
  35. {
  36. ESP_LOGE(TAG, "sLockTimer timer create failed");
  37. return APP_ERROR_CREATE_TIMER_FAILED;
  38. }
  39. mState = kState_LockingCompleted;
  40. mAutoLockTimerArmed = false;
  41. mAutoRelock = false;
  42. mAutoLockDuration = 0;
  43. return CHIP_NO_ERROR;
  44. }
  45. void BoltLockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
  46. {
  47. mActionInitiated_CB = aActionInitiated_CB;
  48. mActionCompleted_CB = aActionCompleted_CB;
  49. }
  50. bool BoltLockManager::IsActionInProgress()
  51. {
  52. return (mState == kState_LockingInitiated || mState == kState_UnlockingInitiated);
  53. }
  54. bool BoltLockManager::IsUnlocked()
  55. {
  56. return (mState == kState_UnlockingCompleted);
  57. }
  58. void BoltLockManager::SetAutoLockDuration(uint32_t aDurationInSecs)
  59. {
  60. mAutoLockDuration = aDurationInSecs;
  61. }
  62. bool BoltLockManager::InitiateAction(int32_t aActor, Action_t aAction)
  63. {
  64. bool action_initiated = false;
  65. State_t new_state;
  66. // Initiate Lock/Unlock Action only when the previous one is complete.
  67. if (mState == kState_LockingCompleted && aAction == UNLOCK_ACTION)
  68. {
  69. action_initiated = true;
  70. new_state = kState_UnlockingInitiated;
  71. }
  72. else if (mState == kState_UnlockingCompleted && aAction == LOCK_ACTION)
  73. {
  74. action_initiated = true;
  75. new_state = kState_LockingInitiated;
  76. }
  77. if (action_initiated)
  78. {
  79. if (mAutoLockTimerArmed && new_state == kState_LockingInitiated)
  80. {
  81. // If auto lock timer has been armed and someone initiates locking,
  82. // cancel the timer and continue as normal.
  83. mAutoLockTimerArmed = false;
  84. CancelTimer();
  85. }
  86. StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
  87. // Since the timer started successfully, update the state and trigger callback
  88. mState = new_state;
  89. if (mActionInitiated_CB)
  90. {
  91. mActionInitiated_CB(aAction, aActor);
  92. }
  93. }
  94. return action_initiated;
  95. }
  96. void BoltLockManager::StartTimer(uint32_t aTimeoutMs)
  97. {
  98. if (xTimerIsTimerActive(sLockTimer))
  99. {
  100. ESP_LOGI(TAG, "app timer already started!");
  101. CancelTimer();
  102. }
  103. // timer is not active, change its period to required value (== restart).
  104. // FreeRTOS- Block for a maximum of 100 ticks if the change period command
  105. // cannot immediately be sent to the timer command queue.
  106. if (xTimerChangePeriod(sLockTimer, (aTimeoutMs / portTICK_PERIOD_MS), 100) != pdPASS)
  107. {
  108. ESP_LOGI(TAG, "sLockTimer timer start() failed");
  109. return;
  110. }
  111. }
  112. void BoltLockManager::CancelTimer(void)
  113. {
  114. if (xTimerStop(sLockTimer, 0) == pdFAIL)
  115. {
  116. ESP_LOGI(TAG, "Lock timer timer stop() failed");
  117. return;
  118. }
  119. }
  120. void BoltLockManager::TimerEventHandler(TimerHandle_t xTimer)
  121. {
  122. // Get lock obj context from timer id.
  123. BoltLockManager * lock = static_cast<BoltLockManager *>(pvTimerGetTimerID(xTimer));
  124. // The timer event handler will be called in the context of the timer task
  125. // once sLockTimer expires. Post an event to apptask queue with the actual handler
  126. // so that the event can be handled in the context of the apptask.
  127. AppEvent event;
  128. event.Type = AppEvent::kEventType_Timer;
  129. event.TimerEvent.Context = lock;
  130. if (lock->mAutoLockTimerArmed)
  131. {
  132. event.Handler = AutoReLockTimerEventHandler;
  133. }
  134. else
  135. {
  136. event.Handler = ActuatorMovementTimerEventHandler;
  137. }
  138. GetAppTask().PostEvent(&event);
  139. }
  140. void BoltLockManager::AutoReLockTimerEventHandler(AppEvent * aEvent)
  141. {
  142. BoltLockManager * lock = static_cast<BoltLockManager *>(aEvent->TimerEvent.Context);
  143. int32_t actor = 0;
  144. // Make sure auto lock timer is still armed.
  145. if (!lock->mAutoLockTimerArmed)
  146. {
  147. return;
  148. }
  149. lock->mAutoLockTimerArmed = false;
  150. ESP_LOGI(TAG, "Auto Re-Lock has been triggered!");
  151. lock->InitiateAction(actor, LOCK_ACTION);
  152. }
  153. void BoltLockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
  154. {
  155. Action_t actionCompleted = INVALID_ACTION;
  156. BoltLockManager * lock = static_cast<BoltLockManager *>(aEvent->TimerEvent.Context);
  157. if (lock->mState == kState_LockingInitiated)
  158. {
  159. lock->mState = kState_LockingCompleted;
  160. actionCompleted = LOCK_ACTION;
  161. }
  162. else if (lock->mState == kState_UnlockingInitiated)
  163. {
  164. lock->mState = kState_UnlockingCompleted;
  165. actionCompleted = UNLOCK_ACTION;
  166. }
  167. if (actionCompleted != INVALID_ACTION)
  168. {
  169. if (lock->mActionCompleted_CB)
  170. {
  171. lock->mActionCompleted_CB(actionCompleted);
  172. }
  173. if (lock->mAutoRelock && actionCompleted == UNLOCK_ACTION)
  174. {
  175. // Start the timer for auto relock
  176. lock->StartTimer(lock->mAutoLockDuration * 1000);
  177. lock->mAutoLockTimerArmed = true;
  178. ESP_LOGI(TAG, "Auto Re-lock enabled. Will be triggered in %u seconds", lock->mAutoLockDuration);
  179. }
  180. }
  181. }