| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- /*
- *
- * Copyright (c) 2020 Project CHIP Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "BoltLockManager.h"
- #include "AppConfig.h"
- #include "AppTask.h"
- #include "esp_log.h"
- #include <freertos/FreeRTOS.h>
- static const char * TAG = "BoltLockManager";
- BoltLockManager BoltLockManager::sLock;
- TimerHandle_t sLockTimer;
- CHIP_ERROR BoltLockManager::Init()
- {
- // Create FreeRTOS sw timer for lock timer.
- sLockTimer = xTimerCreate("lockTmr", // Just a text name, not used by the RTOS kernel
- 1, // == default timer period (mS)
- false, // no timer reload (==one-shot)
- (void *) this, // init timer id = lock obj context
- TimerEventHandler // timer callback handler
- );
- if (sLockTimer == NULL)
- {
- ESP_LOGE(TAG, "sLockTimer timer create failed");
- return APP_ERROR_CREATE_TIMER_FAILED;
- }
- mState = kState_LockingCompleted;
- mAutoLockTimerArmed = false;
- mAutoRelock = false;
- mAutoLockDuration = 0;
- return CHIP_NO_ERROR;
- }
- void BoltLockManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
- {
- mActionInitiated_CB = aActionInitiated_CB;
- mActionCompleted_CB = aActionCompleted_CB;
- }
- bool BoltLockManager::IsActionInProgress()
- {
- return (mState == kState_LockingInitiated || mState == kState_UnlockingInitiated);
- }
- bool BoltLockManager::IsUnlocked()
- {
- return (mState == kState_UnlockingCompleted);
- }
- void BoltLockManager::SetAutoLockDuration(uint32_t aDurationInSecs)
- {
- mAutoLockDuration = aDurationInSecs;
- }
- bool BoltLockManager::InitiateAction(int32_t aActor, Action_t aAction)
- {
- bool action_initiated = false;
- State_t new_state;
- // Initiate Lock/Unlock Action only when the previous one is complete.
- if (mState == kState_LockingCompleted && aAction == UNLOCK_ACTION)
- {
- action_initiated = true;
- new_state = kState_UnlockingInitiated;
- }
- else if (mState == kState_UnlockingCompleted && aAction == LOCK_ACTION)
- {
- action_initiated = true;
- new_state = kState_LockingInitiated;
- }
- if (action_initiated)
- {
- if (mAutoLockTimerArmed && new_state == kState_LockingInitiated)
- {
- // If auto lock timer has been armed and someone initiates locking,
- // cancel the timer and continue as normal.
- mAutoLockTimerArmed = false;
- CancelTimer();
- }
- StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
- // Since the timer started successfully, update the state and trigger callback
- mState = new_state;
- if (mActionInitiated_CB)
- {
- mActionInitiated_CB(aAction, aActor);
- }
- }
- return action_initiated;
- }
- void BoltLockManager::StartTimer(uint32_t aTimeoutMs)
- {
- if (xTimerIsTimerActive(sLockTimer))
- {
- ESP_LOGI(TAG, "app timer already started!");
- CancelTimer();
- }
- // timer is not active, change its period to required value (== restart).
- // FreeRTOS- Block for a maximum of 100 ticks if the change period command
- // cannot immediately be sent to the timer command queue.
- if (xTimerChangePeriod(sLockTimer, (aTimeoutMs / portTICK_PERIOD_MS), 100) != pdPASS)
- {
- ESP_LOGI(TAG, "sLockTimer timer start() failed");
- return;
- }
- }
- void BoltLockManager::CancelTimer(void)
- {
- if (xTimerStop(sLockTimer, 0) == pdFAIL)
- {
- ESP_LOGI(TAG, "Lock timer timer stop() failed");
- return;
- }
- }
- void BoltLockManager::TimerEventHandler(TimerHandle_t xTimer)
- {
- // Get lock obj context from timer id.
- BoltLockManager * lock = static_cast<BoltLockManager *>(pvTimerGetTimerID(xTimer));
- // The timer event handler will be called in the context of the timer task
- // once sLockTimer expires. Post an event to apptask queue with the actual handler
- // so that the event can be handled in the context of the apptask.
- AppEvent event;
- event.Type = AppEvent::kEventType_Timer;
- event.TimerEvent.Context = lock;
- if (lock->mAutoLockTimerArmed)
- {
- event.Handler = AutoReLockTimerEventHandler;
- }
- else
- {
- event.Handler = ActuatorMovementTimerEventHandler;
- }
- GetAppTask().PostEvent(&event);
- }
- void BoltLockManager::AutoReLockTimerEventHandler(AppEvent * aEvent)
- {
- BoltLockManager * lock = static_cast<BoltLockManager *>(aEvent->TimerEvent.Context);
- int32_t actor = 0;
- // Make sure auto lock timer is still armed.
- if (!lock->mAutoLockTimerArmed)
- {
- return;
- }
- lock->mAutoLockTimerArmed = false;
- ESP_LOGI(TAG, "Auto Re-Lock has been triggered!");
- lock->InitiateAction(actor, LOCK_ACTION);
- }
- void BoltLockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
- {
- Action_t actionCompleted = INVALID_ACTION;
- BoltLockManager * lock = static_cast<BoltLockManager *>(aEvent->TimerEvent.Context);
- if (lock->mState == kState_LockingInitiated)
- {
- lock->mState = kState_LockingCompleted;
- actionCompleted = LOCK_ACTION;
- }
- else if (lock->mState == kState_UnlockingInitiated)
- {
- lock->mState = kState_UnlockingCompleted;
- actionCompleted = UNLOCK_ACTION;
- }
- if (actionCompleted != INVALID_ACTION)
- {
- if (lock->mActionCompleted_CB)
- {
- lock->mActionCompleted_CB(actionCompleted);
- }
- if (lock->mAutoRelock && actionCompleted == UNLOCK_ACTION)
- {
- // Start the timer for auto relock
- lock->StartTimer(lock->mAutoLockDuration * 1000);
- lock->mAutoLockTimerArmed = true;
- ESP_LOGI(TAG, "Auto Re-lock enabled. Will be triggered in %u seconds", lock->mAutoLockDuration);
- }
- }
- }
|