Skip to content

Commit

Permalink
[QPG] QPG examples bulk update (#34501)
Browse files Browse the repository at this point in the history
* [QPG] Add TotalOperationalHours counter for switch and TRV

* [QPG] fix for switch  to use correct previousPosition in ShortRelease event

* [QPG] Use identify cluster on endpoint 2 for switch

* feat(multicast): Add multicast binding for Matter Combo Switch
Refs: APPSCS-4571

* [QPG] MultiPress and LongPress implementation for switch

* [INTERNAL] Fix qPinCfg.h error

* Set groups cluster to server in switch.zap and improve command handling for unicast and multicast

* [QPG] PowerSource cluster added

* Restyled by whitespace

* Restyled by clang-format

* Fixed .matter file

---------

Co-authored-by: Dieter Van der Meulen <[email protected]>
Co-authored-by: lucicop <[email protected]>
Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
4 people authored Jul 25, 2024
1 parent 1b1340f commit bfa80b9
Show file tree
Hide file tree
Showing 11 changed files with 1,151 additions and 59 deletions.
3 changes: 3 additions & 0 deletions examples/light-switch-app/qpg/include/AppTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class AppTask
static void FunctionHandler(AppEvent * aEvent);

static void TimerEventHandler(chip::System::Layer * aLayer, void * aAppState);
static void TotalHoursTimerHandler(chip::System::Layer * aLayer, void * aAppState);
static void MultiPressTimeoutHandler(chip::System::Layer * aLayer, void * aAppState);
static void LongPressTimeoutHandler(chip::System::Layer * aLayer, void * aAppState);

static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
static void UpdateLEDs(void);
Expand Down
6 changes: 5 additions & 1 deletion examples/light-switch-app/qpg/include/SwitchManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ class SwitchManager

void Init(void);
static void GenericSwitchInitialPressHandler(AppEvent * aEvent);
static void GenericSwitchReleasePressHandler(AppEvent * aEvent);
static void GenericSwitchShortReleaseHandler(AppEvent * aEvent);
static void GenericSwitchLongReleaseHandler(AppEvent * aEvent);
static void GenericSwitchLongPressHandler(AppEvent * aEvent);
static void GenericSwitchMultipressCompleteHandler(AppEvent * aEvent);
static void GenericSwitchMultipressOngoingHandler(AppEvent * aEvent);
static void ToggleHandler(AppEvent * aEvent);
static void LevelHandler(AppEvent * aEvent);
static void ColorHandler(AppEvent * aEvent);
Expand Down
158 changes: 151 additions & 7 deletions examples/light-switch-app/qpg/src/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ using namespace ::chip;
#include <credentials/DeviceAttestationCredsProvider.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>

#if defined(QORVO_QPINCFG_ENABLE)
#include "qPinCfg.h"
#endif // QORVO_QPINCFG_ENABLE

#include <inet/EndPointStateOpenThread.h>

#include <DeviceInfoProviderImpl.h>
Expand All @@ -58,9 +62,16 @@ using namespace ::chip::DeviceLayer;

#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
#define SWITCH_MULTIPRESS_WINDOW_MS 500
#define SWITCH_LONGPRESS_WINDOW_MS 3000
#define SWITCH_BUTTON_PRESSED 1
#define SWITCH_BUTTON_UNPRESSED 0

#define APP_TASK_STACK_SIZE (2 * 1024)
#define APP_TASK_PRIORITY 2
#define APP_EVENT_QUEUE_SIZE 10
#define SECONDS_IN_HOUR (3600) // we better keep this 3600
#define TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS (1 * SECONDS_IN_HOUR) // increment every hour

namespace {
TaskHandle_t sAppTaskHandle;
Expand All @@ -70,6 +81,9 @@ bool sIsThreadProvisioned = false;
bool sIsThreadEnabled = false;
bool sHaveBLEConnections = false;
bool sIsBLEAdvertisingEnabled = false;
bool sIsMultipressOngoing = false;
bool sLongPressDetected = false;
uint8_t sSwitchButtonState = SWITCH_BUTTON_UNPRESSED;

// NOTE! This key is for test/certification only and should not be available in production devices!
uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
Expand Down Expand Up @@ -141,11 +155,19 @@ void OnTriggerIdentifyEffect(Identify * identify)
}
}

Identify gIdentify = {
Identify gIdentifyEp1 = {
chip::EndpointId{ 1 },
[](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); },
[](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); },
Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator,
Clusters::Identify::IdentifyTypeEnum::kNone,
OnTriggerIdentifyEffect,
};

Identify gIdentifyEp2 = {
chip::EndpointId{ 2 },
[](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); },
[](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); },
Clusters::Identify::IdentifyTypeEnum::kNone,
OnTriggerIdentifyEffect,
};

Expand Down Expand Up @@ -224,6 +246,14 @@ CHIP_ERROR AppTask::Init()
{
CHIP_ERROR err = CHIP_NO_ERROR;

#if defined(QORVO_QPINCFG_ENABLE)
qResult_t res = Q_OK;
res = qPinCfg_Init(NULL);
if (res != Q_OK)
{
ChipLogError(NotSpecified, "qPinCfg_Init failed: %d", res);
}
#endif // QORVO_QPINCFG_ENABLE
PlatformMgr().AddEventHandler(MatterEventHandler, 0);

ChipLogProgress(NotSpecified, "Current Software Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING);
Expand Down Expand Up @@ -255,6 +285,14 @@ CHIP_ERROR AppTask::Init()
sIsBLEAdvertisingEnabled = ConnectivityMgr().IsBLEAdvertisingEnabled();
UpdateLEDs();

err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS),
TotalHoursTimerHandler, this);

if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err));
}

return err;
}

Expand All @@ -275,7 +313,9 @@ void AppTask::AppTaskMain(void * pvParameter)

void AppTask::ButtonEventHandler(uint8_t btnIdx, bool btnPressed)
{
ChipLogProgress(NotSpecified, "ButtonEventHandler %d, %d", btnIdx, btnPressed);
CHIP_ERROR err = CHIP_NO_ERROR;

ChipLogDetail(NotSpecified, "ButtonEventHandler %d, %d", btnIdx, btnPressed);

AppEvent button_event = {};
button_event.Type = AppEvent::kEventType_Button;
Expand All @@ -297,13 +337,54 @@ void AppTask::ButtonEventHandler(uint8_t btnIdx, bool btnPressed)
case APP_FUNCTION2_SWITCH: {
if (!btnPressed)
{
ChipLogProgress(NotSpecified, "Switch release press");
button_event.Handler = SwitchMgr().GenericSwitchReleasePressHandler;
ChipLogDetail(NotSpecified, "Switch button released");

button_event.Handler =
sLongPressDetected ? SwitchMgr().GenericSwitchLongReleaseHandler : SwitchMgr().GenericSwitchShortReleaseHandler;

sIsMultipressOngoing = true;
sSwitchButtonState = SWITCH_BUTTON_UNPRESSED;
sLongPressDetected = false;

chip::DeviceLayer::SystemLayer().CancelTimer(MultiPressTimeoutHandler, NULL);
// we start the MultiPress feature window after releasing the button
err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(SWITCH_MULTIPRESS_WINDOW_MS),
MultiPressTimeoutHandler, NULL);

if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err));
}
}
else
{
ChipLogProgress(NotSpecified, "Switch initial press");
button_event.Handler = SwitchMgr().GenericSwitchInitialPressHandler;
ChipLogDetail(NotSpecified, "Switch button pressed");

sSwitchButtonState = SWITCH_BUTTON_PRESSED;

chip::DeviceLayer::SystemLayer().CancelTimer(LongPressTimeoutHandler, NULL);
// we need to check if this is short or long press
err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(SWITCH_LONGPRESS_WINDOW_MS),
LongPressTimeoutHandler, NULL);

if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err));
}

// if we have active multipress window we need to send extra event
if (sIsMultipressOngoing)
{
ChipLogDetail(NotSpecified, "Switch MultipressOngoing");
button_event.Handler = SwitchMgr().GenericSwitchInitialPressHandler;
sAppTask.PostEvent(&button_event);
chip::DeviceLayer::SystemLayer().CancelTimer(MultiPressTimeoutHandler, NULL);
button_event.Handler = SwitchMgr().GenericSwitchMultipressOngoingHandler;
}
else
{
button_event.Handler = SwitchMgr().GenericSwitchInitialPressHandler;
}
}
break;
}
Expand Down Expand Up @@ -348,6 +429,69 @@ void AppTask::TimerEventHandler(chip::System::Layer * aLayer, void * aAppState)
sAppTask.PostEvent(&event);
}

void AppTask::MultiPressTimeoutHandler(chip::System::Layer * aLayer, void * aAppState)
{
ChipLogDetail(NotSpecified, "MultiPressTimeoutHandler");

sIsMultipressOngoing = false;

AppEvent multipress_event = {};
multipress_event.Type = AppEvent::kEventType_Button;
multipress_event.Handler = SwitchMgr().GenericSwitchMultipressCompleteHandler;

sAppTask.PostEvent(&multipress_event);
}

void AppTask::LongPressTimeoutHandler(chip::System::Layer * aLayer, void * aAppState)
{
ChipLogDetail(NotSpecified, "LongPressTimeoutHandler");

// if the button is still pressed after threshold time, this is a LongPress, otherwise jsut ignore it
if (sSwitchButtonState == SWITCH_BUTTON_PRESSED)
{
sLongPressDetected = true;
AppEvent longpress_event = {};
longpress_event.Type = AppEvent::kEventType_Button;
longpress_event.Handler = SwitchMgr().GenericSwitchLongPressHandler;

sAppTask.PostEvent(&longpress_event);
}
}

void AppTask::TotalHoursTimerHandler(chip::System::Layer * aLayer, void * aAppState)
{
ChipLogDetail(NotSpecified, "HourlyTimer");

CHIP_ERROR err;
uint32_t totalOperationalHours = 0;

err = ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours);

if (err == CHIP_NO_ERROR)
{
ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours +
(TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / SECONDS_IN_HOUR));
}
else if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
{
totalOperationalHours = 0; // set this explicitly to 0 for safety
ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours +
(TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS / SECONDS_IN_HOUR));
}
else
{
ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node");
}

err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(TOTAL_OPERATIONAL_HOURS_SAVE_INTERVAL_SECONDS),
TotalHoursTimerHandler, nullptr);

if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err));
}
}

void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
{
if (aEvent->Type != AppEvent::kEventType_Timer)
Expand Down
83 changes: 76 additions & 7 deletions examples/light-switch-app/qpg/src/SwitchManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
SwitchManager SwitchManager::sSwitch;
using namespace ::chip;
using namespace chip::DeviceLayer;
static uint8_t multiPressCount = 1;

void SwitchManager::Init(void)
{
// init - TODO
uint8_t multiPressMax = 2;
chip::app::Clusters::Switch::Attributes::MultiPressMax::Set(GENERICSWITCH_ENDPOINT_ID, multiPressMax);
}

void SwitchManager::ToggleHandler(AppEvent * aEvent)
Expand All @@ -46,6 +48,7 @@ void SwitchManager::ToggleHandler(AppEvent * aEvent)
data->localEndpointId = SWITCH_ENDPOINT_ID;
data->clusterId = chip::app::Clusters::OnOff::Id;
data->commandId = chip::app::Clusters::OnOff::Commands::Toggle::Id;
data->isGroup = true;

DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
}
Expand Down Expand Up @@ -118,29 +121,95 @@ void SwitchManager::GenericSwitchInitialPressHandler(AppEvent * aEvent)
return;
}

ChipLogProgress(NotSpecified, "GenericSwitchInitialPress new position %d", newPosition);
ChipLogDetail(NotSpecified, "GenericSwitchInitialPress new position %d", newPosition);
SystemLayer().ScheduleLambda([newPosition] {
chip::app::Clusters::Switch::Attributes::CurrentPosition::Set(GENERICSWITCH_ENDPOINT_ID, newPosition);
// InitialPress event takes newPosition as event data
chip::app::Clusters::SwitchServer::Instance().OnInitialPress(GENERICSWITCH_ENDPOINT_ID, newPosition);
});
}

void SwitchManager::GenericSwitchReleasePressHandler(AppEvent * aEvent)
void SwitchManager::GenericSwitchLongPressHandler(AppEvent * aEvent)
{
// Release moves Position from 1 (press) to 0
uint8_t newPosition = 0;
// Press moves Position from 0 (idle) to 1 (press)
uint8_t newPosition = 1;

if (aEvent->Type != AppEvent::kEventType_Button)
{
ChipLogError(NotSpecified, "Event type not supported!");
return;
}

ChipLogProgress(NotSpecified, "GenericSwitchReleasePress new position %d", newPosition);
ChipLogDetail(NotSpecified, "GenericSwitchLongPress new position %d", newPosition);
SystemLayer().ScheduleLambda([newPosition] {
// LongPress event takes newPosition as event data
chip::app::Clusters::SwitchServer::Instance().OnLongPress(GENERICSWITCH_ENDPOINT_ID, newPosition);
});
}

void SwitchManager::GenericSwitchShortReleaseHandler(AppEvent * aEvent)
{
// Release moves Position from 1 (press) to 0
uint8_t newPosition = 0;
uint8_t previousPosition = 1;

if (aEvent->Type != AppEvent::kEventType_Button)
{
ChipLogError(NotSpecified, "Event type not supported!");
return;
}

ChipLogDetail(NotSpecified, "GenericSwitchShortRelease new position %d", newPosition);
SystemLayer().ScheduleLambda([newPosition, previousPosition] {
chip::app::Clusters::Switch::Attributes::CurrentPosition::Set(GENERICSWITCH_ENDPOINT_ID, newPosition);
// Short Release event takes newPosition as event data
chip::app::Clusters::SwitchServer::Instance().OnShortRelease(GENERICSWITCH_ENDPOINT_ID, newPosition);
chip::app::Clusters::SwitchServer::Instance().OnShortRelease(GENERICSWITCH_ENDPOINT_ID, previousPosition);
});
}

void SwitchManager::GenericSwitchLongReleaseHandler(AppEvent * aEvent)
{
// Release moves Position from 1 (press) to 0
uint8_t newPosition = 0;
uint8_t previousPosition = 1;

if (aEvent->Type != AppEvent::kEventType_Button)
{
ChipLogError(NotSpecified, "Event type not supported!");
return;
}

ChipLogDetail(NotSpecified, "GenericSwitchLongRelease new position %d", newPosition);
SystemLayer().ScheduleLambda([newPosition, previousPosition] {
chip::app::Clusters::Switch::Attributes::CurrentPosition::Set(GENERICSWITCH_ENDPOINT_ID, newPosition);
// LongRelease event takes newPosition as event data
chip::app::Clusters::SwitchServer::Instance().OnLongRelease(GENERICSWITCH_ENDPOINT_ID, previousPosition);
});
}

void SwitchManager::GenericSwitchMultipressOngoingHandler(AppEvent * aEvent)
{
uint8_t newPosition = 1;

multiPressCount++;

ChipLogDetail(NotSpecified, "GenericSwitchMultiPressOngoing (%d)", multiPressCount);

SystemLayer().ScheduleLambda([newPosition] {
chip::app::Clusters::SwitchServer::Instance().OnMultiPressOngoing(GENERICSWITCH_ENDPOINT_ID, newPosition, multiPressCount);
});
}

void SwitchManager::GenericSwitchMultipressCompleteHandler(AppEvent * aEvent)
{
uint8_t previousPosition = 0;

ChipLogProgress(NotSpecified, "GenericSwitchMultiPressComplete (%d)", multiPressCount);

SystemLayer().ScheduleLambda([previousPosition] {
chip::app::Clusters::SwitchServer::Instance().OnMultiPressComplete(GENERICSWITCH_ENDPOINT_ID, previousPosition,
multiPressCount);
});

multiPressCount = 1;
}
Loading

0 comments on commit bfa80b9

Please sign in to comment.