diff --git a/examples/thermostat/efr32/README.md b/examples/thermostat/efr32/README.md
index 5bc31b87d2d989..b23e089427e4f3 100644
--- a/examples/thermostat/efr32/README.md
+++ b/examples/thermostat/efr32/README.md
@@ -7,14 +7,22 @@ An example showing the use of CHIP on the Silicon Labs EFR32 MG12.
- [CHIP EFR32 Light Switch Example](#chip-efr32-light-switch-example)
- [Introduction](#introduction)
- [Building](#building)
- - [Note](#note)
+ - [Linux](#linux)
+ - [Mac OS X](#mac-os-x)
- [Flashing the Application](#flashing-the-application)
- [Viewing Logging Output](#viewing-logging-output)
- [Running the Complete Example](#running-the-complete-example)
- [Notes](#notes)
+ - [On Border Router:](#on-border-router)
+ - [On PC(Linux):](#on-pclinux)
- [Running RPC console](#running-rpc-console)
- [Memory settings](#memory-settings)
- [OTA Software Update](#ota-software-update)
+ - [Building options](#building-options)
+ - [Disabling logging](#disabling-logging)
+ - [Debug build / release build](#debug-build--release-build)
+ - [Disabling LCD](#disabling-lcd)
+ - [KVS maximum entry count](#kvs-maximum-entry-count)
@@ -253,14 +261,28 @@ combination with JLinkRTTClient as follows:
**Push Button 0**
- - _Press and Release_ : Start, or restart, BLE advertisement in fast mode. It will advertise in this mode
- for 30 seconds. The device will then switch to a slower interval advertisement.
- After 15 minutes, the advertisement stops.
+ - _Press and Release_ :
- - _Pressed and hold for 6 s_ : Initiates the factory reset of the device.
- Releasing the button within the 6-second window cancels the factory reset
- procedure. **LEDs** blink in unison when the factory reset procedure is
- initiated.
+ - Decreases temperature by 0.01C depending on current mode.
+
+ - Start, or restart, BLE advertisement in fast mode. It will advertise
+ in this mode for 30 seconds. The device will then switch to a
+ slower interval advertisement.
+ After 15 minutes, the advertisement stops.
+
+ - _Pressed and hold for 6.5 s_ : Initiates the factory reset of the device.
+ Releasing button within the 0.5-second window cancels initiation of factory
+ reset.
+ Releasing the button within the 6-second window post that cancels the
+ factory reset procedure. **LEDs** blink in unison when the factory reset
+ procedure is initiated.
+
+ **Push Button 1**
+
+ - _Press and Release_ : Increases temperature by 0.01C depending on current
+ mode.
+
+ - _Pressed and hold for 1 s_ : Toggles the mode of the thermostat.
* You can provision and control the Chip device using the python controller,
[CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md)
diff --git a/examples/thermostat/efr32/include/AppTask.h b/examples/thermostat/efr32/include/AppTask.h
index 800dda99ad37ac..8ff69994575c46 100644
--- a/examples/thermostat/efr32/include/AppTask.h
+++ b/examples/thermostat/efr32/include/AppTask.h
@@ -93,6 +93,15 @@ class AppTask : public BaseApplication
*/
static void OnIdentifyStop(Identify * identify);
+ enum ThermoFunction_t
+ {
+ kFunction_Nothing = 0,
+ kFunction_AppFn = 1,
+ kFunction_Temp = 2,
+
+ kFunction_Invalid
+ } ThermoFunction;
+
private:
static AppTask sAppTask;
@@ -113,10 +122,65 @@ class AppTask : public BaseApplication
static void ButtonHandler(AppEvent * aEvent);
/**
- * @brief PB1 Button event processing function
- * Function triggers a thermostat action sent to the CHIP task
+ * @brief Function called to start the mode timer
*
- * @param aEvent button event being processed
+ * @param aTimeoutMs timer duration in ms
+ */
+ static void StartModeTimer(uint32_t aTimeoutInMs);
+
+ /**
+ * @brief Function to stop the mode timer
+ */
+ static void CancelModeTimer();
+
+ /**
+ * @brief Function called to start the app function timer
+ *
+ * @param aTimeoutMs timer duration in ms
+ */
+ static void StartAppFnTimer(uint32_t aTimeoutInMs);
+
+ /**
+ * @brief Function to stop app function timer
+ */
+ static void CancelAppFnTimer();
+
+ /**
+ * @brief Mode Timer finished callback function
+ * Post an ModeHandler event
+ *
+ * @param xTimer timer that finished
+ */
+ static void ModeTimerEventHandler(TimerHandle_t xTimer);
+
+ /**
+ * @brief App Function Timer finished callback function
+ * Post an AppFnHandler event
+ *
+ * @param xTimer timer that finished
+ */
+ static void AppFnTimerEventHandler(TimerHandle_t xTimer);
+
+ /**
+ * @brief Mode Timer Event processing function
+ * Handles toggling the mode
+ *
+ * @param aEvent post event being processed
+ */
+ static void ModeHandler(AppEvent * aEvent);
+
+ /**
+ * @brief App Function Timer Event processing function
+ * Calls factory reset handler from BaseApplication.cpp
+ *
+ * @param aEvent post event being processed
+ */
+ static void AppFnHandler(AppEvent * aEvent);
+
+ /**
+ * @brief Handles temperature changes depending on timer status
+ *
+ * @param aEvent post event being processed
*/
- static void ThermostatActionEventHandler(AppEvent * aEvent);
+ static void TemperatureHandler(AppEvent * aEvent);
};
diff --git a/examples/thermostat/efr32/src/AppTask.cpp b/examples/thermostat/efr32/src/AppTask.cpp
index 793e79f3ab8145..0ecc65153ae9c9 100644
--- a/examples/thermostat/efr32/src/AppTask.cpp
+++ b/examples/thermostat/efr32/src/AppTask.cpp
@@ -36,7 +36,13 @@
#include
#include
+#include
+#include
#include
+#include
+#include
+#include
+#include
#include
#include
#include
@@ -47,6 +53,7 @@
#include
#include
+
/**********************************************************
* Defines and Constants
*********************************************************/
@@ -54,12 +61,44 @@
#define APP_FUNCTION_BUTTON &sl_button_btn0
#define APP_THERMOSTAT &sl_button_btn1
+#define HEATING_MODE 1
+#define COOLING_MODE 0
+
+#define MODE_TIMER 1000
+#define APP_FN_TIMER 500
+
+#define MIN_HEATINGSETPOINT_LIMIT 700
+#define MAX_HEATINGSETPOINT_LIMIT 3000
+#define MIN_COOLINGSETPOINT_LIMIT 1600
+#define MAX_COOLINGSETPOINT_LIMIT 3200
+
using namespace chip;
using namespace ::chip::DeviceLayer;
+
/**********************************************************
* Variable declarations
*********************************************************/
+
+TimerHandle_t sModeTimer;
+TimerHandle_t sAppFnTimer;
+
+bool mModeTimerActive;
+bool mAppFnTimerActive;
+
+bool startModeTimerVar;
+bool startAppFnTimerVar;
+
+int thermostat_mode = HEATING_MODE;
+
+int16_t heatingSetpoint = 0;
+int16_t coolingSetpoint = 0;
+
+AppTask::ThermoFunction_t btn1State;
+AppTask::ThermoFunction_t btn0State;
+
+AppEvent reset_button_event = {};
+
namespace {
EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
@@ -140,6 +179,30 @@ CHIP_ERROR AppTask::Init()
{
CHIP_ERROR err = CHIP_NO_ERROR;
+ sModeTimer = xTimerCreate("ThermModeTmr", // 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 = app task obj context
+ ModeTimerEventHandler // timer callback handler
+ );
+ if (sModeTimer == NULL)
+ {
+ EFR32_LOG("Creation of sModeTimer failed.");
+ appError(APP_ERROR_CREATE_TIMER_FAILED);
+ }
+
+ sAppFnTimer = xTimerCreate("ThermFnTmr", // 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 = app task obj context
+ AppFnTimerEventHandler // timer callback handler
+ );
+ if (sAppFnTimer == NULL)
+ {
+ EFR32_LOG("Creation of aAppFnTimer failed.");
+ appError(APP_ERROR_CREATE_TIMER_FAILED);
+ }
+
#ifdef DISPLAY_ENABLED
GetLCD().Init((uint8_t *) "Thermostat-App");
#endif
@@ -183,6 +246,31 @@ void AppTask::AppTaskMain(void * pvParameter)
{
sAppTask.DispatchEvent(&event);
eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
+
+ if(startModeTimerVar == true)
+ {
+ StartModeTimer(MODE_TIMER);
+ startModeTimerVar = false;
+ }
+ if(startAppFnTimerVar == true)
+ {
+ StartAppFnTimer(APP_FN_TIMER);
+ startAppFnTimerVar = false;
+ }
+ if ((mModeTimerActive == true) && (btn1State == kFunction_Temp))
+ {
+ CancelModeTimer();
+ TemperatureHandler(&event);
+ startModeTimerVar = false;
+ btn1State = kFunction_Nothing;
+ }
+ if ((mAppFnTimerActive == true) && (btn0State == kFunction_Temp))
+ {
+ CancelAppFnTimer();
+ TemperatureHandler(&event);
+ startAppFnTimerVar = false;
+ btn0State = kFunction_Nothing;
+ }
}
}
}
@@ -205,15 +293,224 @@ void AppTask::OnIdentifyStop(Identify * identify)
#endif
}
-void AppTask::ThermostatActionEventHandler(AppEvent * aEvent)
+
+void AppTask::CancelModeTimer()
+{
+ if (xTimerStop(sModeTimer, 0) == pdFAIL)
+ {
+ EFR32_LOG("thermostat mode timer stop() failed");
+ appError(APP_ERROR_STOP_TIMER_FAILED);
+ }
+ mModeTimerActive = false;
+}
+
+void AppTask::StartModeTimer(uint32_t aTimeoutInMs)
{
- if (aEvent->Type == AppEvent::kEventType_Button)
+ if (xTimerIsTimerActive(sModeTimer))
+ {
+ EFR32_LOG("mode timer already started!");
+ CancelModeTimer();
+ }
+
+ if (xTimerChangePeriod(sModeTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
{
- EFR32_LOG("App Button was pressed!");
- // TODO: Implement button functionnality
+ EFR32_LOG("mode timer start() failed");
+ appError(APP_ERROR_START_TIMER_FAILED);
}
+ mModeTimerActive = true;
}
+
+void AppTask::CancelAppFnTimer()
+{
+ if (xTimerStop(sAppFnTimer, 0) == pdFAIL)
+ {
+ EFR32_LOG("thermostat AppFn timer stop() failed");
+ appError(APP_ERROR_STOP_TIMER_FAILED);
+ }
+ mAppFnTimerActive = false;
+}
+
+void AppTask::StartAppFnTimer(uint32_t aTimeoutInMs)
+{
+ if (xTimerIsTimerActive(sAppFnTimer))
+ {
+ EFR32_LOG("thermostat AppFn timer already started!");
+ CancelAppFnTimer();
+ }
+ if (xTimerChangePeriod(sAppFnTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
+ {
+ EFR32_LOG("thermostat AppFn timer start() failed");
+ appError(APP_ERROR_START_TIMER_FAILED);
+ }
+ mAppFnTimerActive = true;
+}
+
+
+void AppTask::ModeTimerEventHandler(TimerHandle_t xTimer)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.Context = (void *) xTimer;
+ event.Handler = ModeHandler;
+ sAppTask.PostEvent(&event);
+}
+
+void AppTask::AppFnTimerEventHandler(TimerHandle_t xTimer)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.Context = (void *) xTimer;
+ event.Handler = AppFnHandler;
+ sAppTask.PostEvent(&event);
+}
+
+
+void AppTask::TemperatureHandler(AppEvent * aEvent)
+{
+ if (btn1State == kFunction_Temp)
+ {
+ CancelModeTimer();
+
+ chip::EndpointId endpointId = 1;
+
+ if (thermostat_mode == HEATING_MODE)
+ {
+ int16_t maxHeatingSetpointLimit = MAX_HEATINGSETPOINT_LIMIT;
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::Get(endpointId, &heatingSetpoint);
+ chip::app::Clusters::Thermostat::Attributes::AbsMaxHeatSetpointLimit::Get(endpointId, &maxHeatingSetpointLimit);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ if (heatingSetpoint < maxHeatingSetpointLimit)
+ {
+ heatingSetpoint += 1;
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::Set(endpointId, heatingSetpoint);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+ }
+ else
+ {
+ EFR32_LOG("No change: Maximum temperature limit reached.")
+ }
+ }
+ else
+ {
+ int16_t maxCoolingSetpointLimit = MAX_COOLINGSETPOINT_LIMIT;
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::Clusters::Thermostat::Attributes::OccupiedCoolingSetpoint::Get(endpointId, &coolingSetpoint);
+ chip::app::Clusters::Thermostat::Attributes::AbsMaxCoolSetpointLimit::Get(endpointId, &maxCoolingSetpointLimit);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ if (coolingSetpoint < maxCoolingSetpointLimit)
+ {
+ coolingSetpoint += 1;
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::Clusters::Thermostat::Attributes::OccupiedCoolingSetpoint::Set(endpointId, coolingSetpoint);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+ }
+ else
+ {
+ EFR32_LOG("No change: Maximum temperature limit reached.")
+ }
+ }
+ btn1State = kFunction_Nothing;
+ EFR32_LOG("Current temperature set to Heating: %d, Cooling: %d, with Mode: %d", heatingSetpoint, coolingSetpoint, thermostat_mode);
+ }
+ else if (btn0State == kFunction_Temp)
+ {
+ CancelAppFnTimer();
+
+ chip::EndpointId endpointId = 1;
+
+ if (thermostat_mode == HEATING_MODE)
+ {
+ int16_t minHeatingSetpointLimit = MIN_HEATINGSETPOINT_LIMIT;
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::Get(endpointId, &heatingSetpoint);
+ chip::app::Clusters::Thermostat::Attributes::AbsMinHeatSetpointLimit::Get(endpointId, &minHeatingSetpointLimit);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ if (heatingSetpoint > minHeatingSetpointLimit)
+ {
+ heatingSetpoint -= 1;
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::Set(endpointId, heatingSetpoint);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+ }
+ else
+ {
+ EFR32_LOG("No change: Minimum temperature limit reached.")
+ }
+ }
+ else
+ {
+ int16_t minCoolingSetpointLimit = MIN_COOLINGSETPOINT_LIMIT;
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::Clusters::Thermostat::Attributes::OccupiedCoolingSetpoint::Get(endpointId, &coolingSetpoint);
+ chip::app::Clusters::Thermostat::Attributes::AbsMinCoolSetpointLimit::Get(endpointId, &minCoolingSetpointLimit);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ if (coolingSetpoint > minCoolingSetpointLimit)
+ {
+ coolingSetpoint -= 1;
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ chip::app::Clusters::Thermostat::Attributes::OccupiedCoolingSetpoint::Set(endpointId, coolingSetpoint);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+ }
+ else
+ {
+ EFR32_LOG("No change: Minimum temperature limit reached.")
+ }
+ }
+ btn0State = kFunction_Nothing;
+ EFR32_LOG("Current temperature set to Heating: %d, Cooling: %d, with Mode: %d", heatingSetpoint, coolingSetpoint, thermostat_mode);
+ }
+}
+
+
+void AppTask::ModeHandler(AppEvent * aEvent)
+{
+ if (aEvent->Type != AppEvent::kEventType_Timer)
+ {
+ return;
+ }
+
+ if (thermostat_mode == HEATING_MODE)
+ {
+ thermostat_mode = COOLING_MODE;
+ }
+ else
+ {
+ thermostat_mode = HEATING_MODE;
+ }
+ EFR32_LOG("Thermostat Mode set to: %d, with current temperature Heating: %d, Cooling: %d", thermostat_mode, heatingSetpoint, coolingSetpoint);
+ btn1State = kFunction_Nothing;
+ CancelModeTimer();
+}
+
+
+void AppTask::AppFnHandler(AppEvent * aEvent)
+{
+ if (aEvent->Type != AppEvent::kEventType_Timer)
+ {
+ return;
+ }
+ EFR32_LOG("Initiating Factory Reset. Release button within %ums to stop.", APP_FN_TIMER);
+ reset_button_event.Handler = BaseApplication::ButtonHandler;
+ sAppTask.PostEvent(&reset_button_event);
+ btn0State = kFunction_Nothing;
+}
+
+
void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction)
{
if (buttonHandle == NULL)
@@ -225,14 +522,58 @@ void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAc
button_event.Type = AppEvent::kEventType_Button;
button_event.ButtonEvent.Action = btnAction;
- if (buttonHandle == APP_THERMOSTAT && btnAction == SL_SIMPLE_BUTTON_PRESSED)
+ if (buttonHandle == APP_THERMOSTAT)
{
- button_event.Handler = ThermostatActionEventHandler;
+ if (btnAction == SL_SIMPLE_BUTTON_PRESSED)
+ {
+ btn1State = kFunction_AppFn;
+ startModeTimerVar = true;
+ button_event.Handler = ModeHandler;
+ }
+ else
+ {
+ if (mModeTimerActive == true)
+ {
+ btn1State = kFunction_Temp;
+ }
+ else
+ {
+ btn1State = kFunction_Nothing;
+ }
+ startModeTimerVar = false;
+ button_event.Handler = TemperatureHandler;
+ }
sAppTask.PostEvent(&button_event);
}
+
else if (buttonHandle == APP_FUNCTION_BUTTON)
{
- button_event.Handler = BaseApplication::ButtonHandler;
+ if (btnAction)
+ {
+ reset_button_event.Type = AppEvent::kEventType_Button;
+ reset_button_event.ButtonEvent.Action = btnAction;
+
+ btn0State = kFunction_AppFn;
+ startAppFnTimerVar = true;
+ button_event.Handler = AppFnHandler;
+ reset_button_event.Handler = AppFnHandler;
+ }
+ else
+ {
+ reset_button_event.ButtonEvent.Action = btnAction;
+
+ if (mAppFnTimerActive == true)
+ {
+ btn0State = kFunction_Temp;
+ }
+ else
+ {
+ btn0State = kFunction_Nothing;
+ }
+ startAppFnTimerVar = false;
+ button_event.Handler = TemperatureHandler;
+ }
sAppTask.PostEvent(&button_event);
+ sAppTask.PostEvent(&reset_button_event);
}
-}
+}
\ No newline at end of file