3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2020 Texas Instruments Incorporated
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.
21 #include "AppConfig.h"
27 #include <platform/CHIPDeviceLayer.h>
28 #include <support/CHIPMem.h>
29 #include <support/CHIPPlatformMemory.h>
31 #include "OnboardingCodesUtil.h"
33 #include "DataModelHandler.h"
35 #include <ti/drivers/apps/Button.h>
36 #include <ti/drivers/apps/LED.h>
39 #include <ti_drivers_config.h>
41 #define APP_TASK_STACK_SIZE (4096)
42 #define APP_TASK_PRIORITY 4
43 #define APP_EVENT_QUEUE_SIZE 10
45 using namespace ::chip::DeviceLayer;
47 static TaskHandle_t sAppTaskHandle;
48 static QueueHandle_t sAppEventQueue;
50 static LED_Handle sAppRedHandle;
51 static LED_Handle sAppGreenHandle;
52 static Button_Handle sAppLeftHandle;
53 static Button_Handle sAppRightHandle;
55 AppTask AppTask::sAppTask;
57 int AppTask::StartAppTask()
61 sAppEventQueue = xQueueCreate(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent));
62 if (sAppEventQueue == NULL)
64 PLAT_LOG("Failed to allocate app event queue");
70 if (xTaskCreate(AppTaskMain, "APP", APP_TASK_STACK_SIZE / sizeof(StackType_t), NULL, APP_TASK_PRIORITY, &sAppTaskHandle) !=
73 PLAT_LOG("Failed to create app task");
82 int ret = CHIP_ERROR_MAX;
84 Button_Params buttionParams;
85 ConnectivityManager::ThreadPollingConfig pollingConfig;
89 // Init Chip memory management before the stack
90 chip::Platform::MemoryInit();
92 ret = PlatformMgr().InitChipStack();
93 if (ret != CHIP_NO_ERROR)
95 PLAT_LOG("PlatformMgr().InitChipStack() failed");
100 ret = ThreadStackMgr().InitThreadStack();
101 if (ret != CHIP_NO_ERROR)
103 PLAT_LOG("ThreadStackMgr().InitThreadStack() failed");
108 ret = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router);
109 if (ret != CHIP_NO_ERROR)
111 PLAT_LOG("ConnectivityMgr().SetThreadDeviceType() failed");
116 pollingConfig.Clear();
117 pollingConfig.ActivePollingIntervalMS = 5000; // ms
118 pollingConfig.InactivePollingIntervalMS = 5000; // ms
120 ret = ConnectivityMgr().SetThreadPollingConfig(pollingConfig);
121 if (ret != CHIP_NO_ERROR)
123 PLAT_LOG("ConnectivityMgr().SetThreadPollingConfig() failed");
128 ret = PlatformMgr().StartEventLoopTask();
129 if (ret != CHIP_NO_ERROR)
131 PLAT_LOG("PlatformMgr().StartEventLoopTask() failed");
136 ret = ThreadStackMgrImpl().StartThreadTask();
137 if (ret != CHIP_NO_ERROR)
139 PLAT_LOG("ThreadStackMgr().StartThreadTask() failed");
144 // Init ZCL Data Model and start server
145 PLAT_LOG("Initialize Server");
149 PLAT_LOG("Initialize LEDs");
152 LED_Params_init(&ledParams); // default PWM LED
153 sAppRedHandle = LED_open(CONFIG_LED_RED, &ledParams);
154 LED_setOff(sAppRedHandle);
156 LED_Params_init(&ledParams); // default PWM LED
157 sAppGreenHandle = LED_open(CONFIG_LED_GREEN, &ledParams);
158 LED_setOff(sAppGreenHandle);
160 // Initialize buttons
161 PLAT_LOG("Initialize buttons");
164 Button_Params_init(&buttionParams);
165 buttionParams.buttonEventMask = Button_EV_CLICKED | Button_EV_LONGCLICKED;
166 buttionParams.longPressDuration = 1000U; // ms
167 sAppLeftHandle = Button_open(CONFIG_BTN_LEFT, ButtonLeftEventHandler, &buttionParams);
169 Button_Params_init(&buttionParams);
170 buttionParams.buttonEventMask = Button_EV_CLICKED | Button_EV_LONGCLICKED;
171 buttionParams.longPressDuration = 1000U; // ms
172 sAppRightHandle = Button_open(CONFIG_BTN_RIGHT, ButtonRightEventHandler, &buttionParams);
174 // Initialize BoltLock module
175 PLAT_LOG("Initialize BoltLock");
176 BoltLockMgr().Init();
178 BoltLockMgr().SetCallbacks(ActionInitiated, ActionCompleted);
180 ConfigurationMgr().LogDeviceConfig();
182 // QR code will be used with CHIP Tool
183 PrintOnboardingCodes(chip::RendezvousInformationFlags::kBLE);
188 void AppTask::AppTaskMain(void * pvParameter)
196 /* Task pend until we have stuff to do */
197 if (xQueueReceive(sAppEventQueue, &event, portMAX_DELAY) == pdTRUE)
199 sAppTask.DispatchEvent(&event);
204 void AppTask::PostEvent(const AppEvent * aEvent)
206 if (xQueueSend(sAppEventQueue, aEvent, 0) != pdPASS)
208 /* Failed to post the message */
212 void AppTask::ButtonLeftEventHandler(Button_Handle handle, Button_EventMask events)
215 event.Type = AppEvent::kEventType_ButtonLeft;
217 if (events & Button_EV_CLICKED)
219 event.ButtonEvent.Type = AppEvent::kAppEventButtonType_Clicked;
221 else if (events & Button_EV_LONGCLICKED)
223 event.ButtonEvent.Type = AppEvent::kAppEventButtonType_LongClicked;
225 // button callbacks are in ISR context
226 if (xQueueSendFromISR(sAppEventQueue, &event, NULL) != pdPASS)
228 /* Failed to post the message */
232 void AppTask::ButtonRightEventHandler(Button_Handle handle, Button_EventMask events)
235 event.Type = AppEvent::kEventType_ButtonRight;
237 if (events & Button_EV_CLICKED)
239 event.ButtonEvent.Type = AppEvent::kAppEventButtonType_Clicked;
241 else if (events & Button_EV_LONGCLICKED)
243 event.ButtonEvent.Type = AppEvent::kAppEventButtonType_LongClicked;
245 // button callbacks are in ISR context
246 if (xQueueSendFromISR(sAppEventQueue, &event, NULL) != pdPASS)
248 /* Failed to post the message */
252 void AppTask::ActionInitiated(BoltLockManager::Action_t aAction, int32_t aActor)
254 // If the action has been initiated by the lock, update the bolt lock trait
255 // and start flashing the LEDs rapidly to indicate action initiation.
256 if (aAction == BoltLockManager::LOCK_ACTION)
258 PLAT_LOG("Lock initiated");
261 else if (aAction == BoltLockManager::UNLOCK_ACTION)
263 PLAT_LOG("Unlock initiated");
267 LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX);
268 LED_startBlinking(sAppGreenHandle, 50 /* ms */, LED_BLINK_FOREVER);
269 LED_setOn(sAppRedHandle, LED_BRIGHTNESS_MAX);
270 LED_startBlinking(sAppRedHandle, 110 /* ms */, LED_BLINK_FOREVER);
273 void AppTask::ActionCompleted(BoltLockManager::Action_t aAction)
275 // if the action has been completed by the lock, update the bolt lock trait.
276 // Turn on the lock LED if in a LOCKED state OR
277 // Turn off the lock LED if in an UNLOCKED state.
278 if (aAction == BoltLockManager::LOCK_ACTION)
280 PLAT_LOG("Lock completed");
281 LED_stopBlinking(sAppGreenHandle);
282 LED_setOn(sAppGreenHandle, LED_BRIGHTNESS_MAX);
283 LED_stopBlinking(sAppRedHandle);
284 LED_setOn(sAppRedHandle, LED_BRIGHTNESS_MAX);
286 else if (aAction == BoltLockManager::UNLOCK_ACTION)
288 PLAT_LOG("Unlock completed");
289 LED_stopBlinking(sAppGreenHandle);
290 LED_setOff(sAppGreenHandle);
291 LED_stopBlinking(sAppRedHandle);
292 LED_setOff(sAppRedHandle);
296 void AppTask::DispatchEvent(AppEvent * aEvent)
298 switch (aEvent->Type)
300 case AppEvent::kEventType_ButtonLeft:
301 if (AppEvent::kAppEventButtonType_Clicked == aEvent->ButtonEvent.Type)
303 if (!BoltLockMgr().IsUnlocked())
305 BoltLockMgr().InitiateAction(0, BoltLockManager::UNLOCK_ACTION);
308 else if (AppEvent::kAppEventButtonType_LongClicked == aEvent->ButtonEvent.Type)
310 // Disable BLE advertisements
311 if (ConnectivityMgr().IsBLEAdvertisingEnabled())
313 ConnectivityMgr().SetBLEAdvertisingEnabled(false);
314 PLAT_LOG("Disabled BLE Advertisements");
319 case AppEvent::kEventType_ButtonRight:
320 if (AppEvent::kAppEventButtonType_Clicked == aEvent->ButtonEvent.Type)
322 if (BoltLockMgr().IsUnlocked())
324 BoltLockMgr().InitiateAction(0, BoltLockManager::LOCK_ACTION);
327 else if (AppEvent::kAppEventButtonType_LongClicked == aEvent->ButtonEvent.Type)
329 // Enable BLE advertisements
330 if (!ConnectivityMgr().IsBLEAdvertisingEnabled())
332 ConnectivityMgr().SetBLEAdvertisingEnabled(true);
333 PLAT_LOG("Enabled BLE Advertisements");
338 case AppEvent::kEventType_AppEvent:
339 if (NULL != aEvent->Handler)
341 aEvent->Handler(aEvent);
345 case AppEvent::kEventType_None: