Skip to content

Commit

Permalink
Pull request project-chip#10: Example newLight
Browse files Browse the repository at this point in the history
Merge in WMN_TOOLS/matter from example_newLight to silabs

Squashed commit of the following:

commit 4bf0c26bd4829ec146574c99a77e4c58d242af21
Author: Elfelsoufi-SiLabs <moaminee@silabs.com>
Date:   Fri Jul 15 16:28:07 2022 -0400

    ✨ Code improvements.

commit 0cd0466e28a0e712636bce13ade7498a5ef47d3f
Author: Elfelsoufi-SiLabs <moaminee@silabs.com>
Date:   Thu Jul 14 19:27:00 2022 -0400

    ⌛️ Update the light app to use the new GSDK pwm drivers.

commit dd9ecb156626b149cfdce49ec93e776499439594
Author: Elfelsoufi-SiLabs <moaminee@silabs.com>
Date:   Mon Jul 11 20:34:22 2022 -0400

    🏗  Remove int usage and code clarifications.

commit b745a8622636a608aeb869cab0f3106ac44773aa
Author: Elfelsoufi-SiLabs <moaminee@silabs.com>
Date:   Mon Jul 4 19:08:22 2022 -0400

    🛡  Include guards for incompatible boards.

commit 2bde7a13337f2658ec7de4d8c37e7b00821722c9
Author: Elfelsoufi-SiLabs <moaminee@silabs.com>
Date:   Wed Jun 29 16:48:22 2022 -0400

    ✨ Code improvements.

commit 9fbb2497e7be70c97a70ad694e757e1009c5f837
Author: Elfelsoufi-SiLabs <moaminee@silabs.com>
Date:   Mon Jun 27 22:07:20 2022 -0400

    🎨 Add Color Control.

commit a3640854c813350323b7be18e8b7040c5c9fdfb8
Author: Elfelsoufi-SiLabs <moaminee@silabs.com>
Date:   Mon Jun 20 11:01:09 2022 -0400

    →← Fix merge conflict.
  • Loading branch information
Mohamed Amine Elfelsoufi authored and jmartinez-silabs committed May 25, 2023
1 parent c1f3d66 commit f4dad54
Show file tree
Hide file tree
Showing 9 changed files with 1,035 additions and 12 deletions.
17 changes: 17 additions & 0 deletions silabs_examples/sl-newLight/efr32/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ declare_args() {

# Enables LCD Qr Code on supported devices
show_qr_code = true

# Enables RGB LEDs on supported devices
rgb_led = false
}

# Sanity check
Expand All @@ -75,9 +78,16 @@ if (efr32_board == "BRD4166A" || efr32_board == "BRD4180A") {
show_qr_code = false
}

if (efr32_board == "BRD4166A" || efr32_board == "BRD4160A" || efr32_board == "BRD2207A") {
rgb_led = true
}

# Enables LCD on supported devices
lcd_on = show_qr_code

# Enables RGB LEDs on supported devices
rgb_on = rgb_led

# WiFi settings
if (chip_enable_wifi) {
wifi_sdk_dir = "${chip_root}/third_party/efr32_sdk/repo/matter/wifi"
Expand Down Expand Up @@ -109,6 +119,7 @@ efr32_sdk("sdk") {
include_dirs = [
"${chip_root}/src/platform/EFR32",
"${efr32_project_dir}/include",
"${efr32_project_dir}/light_modules",
"${examples_plat_dir}",
"${chip_root}/src/lib",
]
Expand Down Expand Up @@ -168,6 +179,7 @@ efr32_executable("newLight_app") {
"src/AppTask.cpp",
"src/ZclCallbacks.cpp",
"src/main.cpp",
"light_modules/LightingManager.cpp",
]

if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli) {
Expand Down Expand Up @@ -245,6 +257,11 @@ efr32_executable("newLight_app") {
}
}

if (rgb_on) {
sources += [ "light_modules/led_widget_rgb.cpp" ]
defines += [ "RGB_LED_ENABLED" ]
}

if (chip_enable_pw_rpc) {
defines += [
"PW_RPC_ENABLED",
Expand Down
4 changes: 2 additions & 2 deletions silabs_examples/sl-newLight/efr32/include/AppConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@

#include "efr32_utils.h"

// ---- Template Example App Config ----
// ---- newLight Example App Config ----

#define APP_TASK_NAME "TEMPLATE"
#define APP_TASK_NAME "NEWLIGHT"

// Time it takes in ms for the simulated actuator to move from one
// state to another.
Expand Down
7 changes: 7 additions & 0 deletions silabs_examples/sl-newLight/efr32/include/AppTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "AppEvent.h"
#include "FreeRTOS.h"
#include "LightingManager.h"
#include "sl_simple_button_instances.h"

#include "timers.h" // provides FreeRTOS timer support
Expand All @@ -45,6 +46,7 @@ class AppTask
CHIP_ERROR StartAppTask();
static void AppTaskMain(void * pvParameter);

void PostLightActionRequest(int32_t aActor, LightingManager::Action_t aAction);
void PostEvent(const AppEvent * event);

void ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction);
Expand All @@ -54,12 +56,17 @@ class AppTask

CHIP_ERROR Init();

static void ActionInitiated(LightingManager::Action_t aAction, int32_t aActor);
static void ActionCompleted(LightingManager::Action_t aAction);
static void ActionChangeLight(LightingManager::Action_t aAction, uint16_t endpoint, uint8_t value);

void CancelTimer(void);

void DispatchEvent(AppEvent * event);

static void FunctionTimerEventHandler(AppEvent * aEvent);
static void FunctionHandler(AppEvent * aEvent);
static void LightActionEventHandler(AppEvent * aEvent);
static void TimerEventHandler(TimerHandle_t xTimer);

static void UpdateClusterState(intptr_t context);
Expand Down
256 changes: 256 additions & 0 deletions silabs_examples/sl-newLight/efr32/light_modules/LightingManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
/*
*
* Copyright (c) 2020 Project CHIP Authors
* Copyright (c) 2019 Google LLC.
* All rights reserved.
*
* 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 "LightingManager.h"

#include "AppConfig.h"
#include "AppTask.h"
#include <FreeRTOS.h>

#include <app/clusters/on-off-server/on-off-server.h>

using namespace chip;
using namespace ::chip::DeviceLayer;

LightingManager LightingManager::sLight;

TimerHandle_t sLightTimer;

CHIP_ERROR LightingManager::Init()
{
// Create FreeRTOS sw timer for light timer.
sLightTimer = xTimerCreate("lightTmr", // 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 = light obj context
TimerEventHandler // timer callback handler
);

if (sLightTimer == NULL)
{
EFR32_LOG("sLightTimer timer create failed");
return APP_ERROR_CREATE_TIMER_FAILED;
}

bool currentLedState;
// read current on/off value on endpoint one.
chip::DeviceLayer::PlatformMgr().LockChipStack();
OnOffServer::Instance().getOnOffValue(1, &currentLedState);
chip::DeviceLayer::PlatformMgr().UnlockChipStack();

mState = currentLedState ? kState_OnCompleted : kState_OffCompleted;
mAutoTurnOffTimerArmed = false;
mAutoTurnOff = false;
mAutoTurnOffDuration = 0;

return CHIP_NO_ERROR;
}

void LightingManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
{
mActionInitiated_CB = aActionInitiated_CB;
mActionCompleted_CB = aActionCompleted_CB;
}

void LightingManager::SetLightCallbacks(Callback_fn_set_light aChangeLight_CB)
{
mChangeLight_CB = aChangeLight_CB;
}

bool LightingManager::IsActionInProgress()
{
return (mState == kState_OffInitiated || mState == kState_OnInitiated);
}

bool LightingManager::IsLightOn()
{
return (mState == kState_OnCompleted);
}

void LightingManager::EnableAutoTurnOff(bool aOn)
{
mAutoTurnOff = aOn;
}

void LightingManager::SetAutoTurnOffDuration(uint32_t aDurationInSecs)
{
mAutoTurnOffDuration = aDurationInSecs;
}

bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction)
{
bool action_initiated = false;
State_t new_state;

// Initiate Turn On/Off Action only when the previous one is complete.
if (mState == kState_OffCompleted && aAction == ON_ACTION)
{
action_initiated = true;

new_state = kState_OnInitiated;
}
else if (mState == kState_OnCompleted && aAction == OFF_ACTION)
{
action_initiated = true;

new_state = kState_OffInitiated;
}

if (action_initiated)
{
if (mAutoTurnOffTimerArmed && new_state == kState_OffInitiated)
{
// If auto turn off timer has been armed and someone initiates turning off,
// cancel the timer and continue as normal.
mAutoTurnOffTimerArmed = 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;
}

bool LightingManager::InitiateActionLight(int32_t aActor, Action_t aAction, uint16_t endpoint, uint8_t value)
{
bool action_initiated = false;
bool onoff_complete = (mState == kState_OnCompleted || mState == kState_OffCompleted);
bool led_action = ((aAction == MOVE_TO_LEVEL) || (aAction == MOVE_TO_HUE) || (aAction == MOVE_TO_SAT));

if (onoff_complete && led_action)
{
action_initiated = true;
mChangeLight_CB(aAction, endpoint, value);
}

return action_initiated;
}

void LightingManager::StartTimer(uint32_t aTimeoutMs)
{
if (xTimerIsTimerActive(sLightTimer))
{
EFR32_LOG("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(sLightTimer, (aTimeoutMs / portTICK_PERIOD_MS), 100) != pdPASS)
{
EFR32_LOG("sLightTimer timer start() failed");
appError(APP_ERROR_START_TIMER_FAILED);
}
}

void LightingManager::CancelTimer(void)
{
if (xTimerStop(sLightTimer, 0) == pdFAIL)
{
EFR32_LOG("sLightTimer stop() failed");
appError(APP_ERROR_STOP_TIMER_FAILED);
}
}

void LightingManager::TimerEventHandler(TimerHandle_t xTimer)
{
// Get light obj context from timer id.
LightingManager * light = static_cast<LightingManager *>(pvTimerGetTimerID(xTimer));

// The timer event handler will be called in the context of the timer task
// once sLightTimer 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 = light;
if (light->mAutoTurnOffTimerArmed)
{
event.Handler = AutoTurnOffTimerEventHandler;
}
else
{
event.Handler = ActuatorMovementTimerEventHandler;
}
GetAppTask().PostEvent(&event);
}

void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent)
{
LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
int32_t actor = 0;

// Make sure auto turn off timer is still armed.
if (!light->mAutoTurnOffTimerArmed)
{
return;
}

light->mAutoTurnOffTimerArmed = false;

EFR32_LOG("Auto Turn Off has been triggered!");

light->InitiateAction(actor, OFF_ACTION);
}

void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
{
Action_t actionCompleted = INVALID_ACTION;

LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);

if (light->mState == kState_OffInitiated)
{
light->mState = kState_OffCompleted;
actionCompleted = OFF_ACTION;
}
else if (light->mState == kState_OnInitiated)
{
light->mState = kState_OnCompleted;
actionCompleted = ON_ACTION;
}

if (actionCompleted != INVALID_ACTION)
{
if (light->mActionCompleted_CB)
{
light->mActionCompleted_CB(actionCompleted);
}

if (light->mAutoTurnOff && actionCompleted == ON_ACTION)
{
// Start the timer for auto turn off
light->StartTimer(light->mAutoTurnOffDuration * 1000);

light->mAutoTurnOffTimerArmed = true;

EFR32_LOG("Auto Turn off enabled. Will be triggered in %u seconds", light->mAutoTurnOffDuration);
}
}
}

0 comments on commit f4dad54

Please sign in to comment.