[Silabs] Update the efr32 Thermostat app (#23408)
* Update the efr32 Thermostat app, Use the temperature sensor when available, add a LCD UI for thermostat
* Address PR comments, Cleanup rebase and regen
diff --git a/examples/platform/efr32/TemperatureSensor.cpp b/examples/platform/efr32/TemperatureSensor.cpp
new file mode 100644
index 0000000..69ba106
--- /dev/null
+++ b/examples/platform/efr32/TemperatureSensor.cpp
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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 "TemperatureSensor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// This is a C implementation. Need the ifdef __cplusplus else we get linking issues
+#include "sl_sensor_rht.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+namespace TemperatureSensor {
+constexpr uint16_t kSensorTemperatureOffset = 800;
+
+sl_status_t Init()
+{
+ return sl_sensor_rht_init();
+}
+
+sl_status_t GetTemp(uint32_t * relativeHumidity, int16_t * temperature)
+{
+ // Sensor resolution 0.001 C
+ // DataModel resolution 0.01 C
+ int32_t temp;
+ sl_status_t status = sl_sensor_rht_get(relativeHumidity, &temp);
+ *temperature = static_cast<int16_t>(temp / 10) - kSensorTemperatureOffset;
+ return status;
+}
+}; // namespace TemperatureSensor
diff --git a/examples/platform/efr32/TemperatureSensor.h b/examples/platform/efr32/TemperatureSensor.h
new file mode 100644
index 0000000..116287e
--- /dev/null
+++ b/examples/platform/efr32/TemperatureSensor.h
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "sl_status.h"
+#include <stdint.h>
+
+namespace TemperatureSensor {
+sl_status_t Init();
+sl_status_t GetTemp(uint32_t * relativeHumidity, int16_t * temperature);
+}; // namespace TemperatureSensor
diff --git a/examples/platform/efr32/display/lcd.cpp b/examples/platform/efr32/display/lcd.cpp
index e737702..8e6b38e 100644
--- a/examples/platform/efr32/display/lcd.cpp
+++ b/examples/platform/efr32/display/lcd.cpp
@@ -135,8 +135,20 @@
void SilabsLCD::WriteDemoUI()
{
Clear();
- demoUIClearMainScreen(mName);
- demoUIDisplayApp(dState.mainState);
+ if (customUI != nullptr)
+ {
+ customUI(&glibContext);
+ }
+ else
+ {
+ demoUIClearMainScreen(mName);
+ demoUIDisplayApp(dState.mainState);
+ }
+}
+
+void SilabsLCD::SetCustomUI(customUICB cb)
+{
+ customUI = cb;
}
#ifdef QR_CODE_ENABLED
diff --git a/examples/platform/efr32/display/lcd.h b/examples/platform/efr32/display/lcd.h
index c9729e1..d375b7a 100644
--- a/examples/platform/efr32/display/lcd.h
+++ b/examples/platform/efr32/display/lcd.h
@@ -33,12 +33,15 @@
{
public:
+ typedef void (*customUICB)(GLIB_Context_t * context);
CHIP_ERROR Init(uint8_t * name = nullptr, bool initialState = false);
void * Context();
int Clear(void);
int DrawPixel(void * pContext, int32_t x, int32_t y);
int Update(void);
void WriteDemoUI(bool state);
+ void SetCustomUI(customUICB cb);
+
#ifdef QR_CODE_ENABLED
void SetQRCode(uint8_t * str, uint32_t size);
void ShowQRCode(bool show, bool forceRefresh = false);
@@ -66,6 +69,6 @@
#else
uint8_t mName[APP_NAME_MAX_LENGTH + 1];
#endif
-
- DemoState_t dState;
+ customUICB customUI = nullptr;
+ DemoState_t dState;
};
diff --git a/examples/thermostat/efr32/BUILD.gn b/examples/thermostat/efr32/BUILD.gn
index da732a2..690023d 100644
--- a/examples/thermostat/efr32/BUILD.gn
+++ b/examples/thermostat/efr32/BUILD.gn
@@ -33,6 +33,7 @@
efr32_project_dir = "${chip_root}/examples/thermostat/efr32"
examples_plat_dir = "${chip_root}/examples/platform/efr32"
+efr32_sdk_root = "${chip_root}/third_party/silabs/gecko_sdk"
declare_args() {
# Dump memory usage at link time.
@@ -59,6 +60,10 @@
# Argument to Disable IPv4 for wifi(rs911)
chip_enable_wifi_ipv4 = false
+
+ # Enable the temperature sensor
+ # Some boards do not have a temperature sensor
+ use_temp_sensor = silabs_board != "BRD2703A" && silabs_board != "BRD4319A"
}
declare_args() {
@@ -133,6 +138,7 @@
"${efr32_project_dir}/include",
"${examples_plat_dir}",
"${chip_root}/src/lib",
+ "${efr32_sdk_root}/app/common/util/app_assert",
]
defines = [
@@ -172,6 +178,18 @@
defines += [ "SL_WFX_CONFIG_SCAN" ]
}
}
+ if (use_temp_sensor) {
+ include_dirs += [
+ "${efr32_sdk_root}/platform/driver/i2cspm/inc",
+ "${efr32_sdk_root}/app/bluetooth/common/sensor_rht",
+ "${efr32_sdk_root}/app/bluetooth/common/sensor_rht/config",
+ "${efr32_sdk_root}/hardware/driver/si70xx/inc",
+ "${efr32_sdk_root}/app/bluetooth/common/sensor_select",
+ "${efr32_sdk_root}/platform/common/config",
+ ]
+
+ defines += [ "USE_TEMP_SENSOR" ]
+ }
}
efr32_executable("thermostat_app") {
@@ -186,6 +204,8 @@
"${examples_plat_dir}/init_efrPlatform.cpp",
"${examples_plat_dir}/matter_config.cpp",
"src/AppTask.cpp",
+ "src/SensorManager.cpp",
+ "src/TemperatureManager.cpp",
"src/ZclCallbacks.cpp",
"src/main.cpp",
]
@@ -194,6 +214,19 @@
sources += [ "${examples_plat_dir}/LEDWidget.cpp" ]
}
+ if (use_temp_sensor) {
+ sources += [
+ "${efr32_sdk_root}/app/bluetooth/common/sensor_rht/sl_sensor_rht.c",
+ "${efr32_sdk_root}/app/bluetooth/common/sensor_select/sl_sensor_select.c",
+ "${efr32_sdk_root}/hardware/driver/si70xx/src/sl_si70xx.c",
+ "${efr32_sdk_root}/platform/common/src/sl_status.c",
+ "${efr32_sdk_root}/platform/driver/i2cspm/src/sl_i2cspm.c",
+ "${efr32_sdk_root}/platform/emlib/src/em_i2c.c",
+ "${examples_plat_dir}/TemperatureSensor.cpp",
+ "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_i2cspm_init.c",
+ ]
+ }
+
if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli ||
use_wf200 || use_rs911x) {
sources += [ "${examples_plat_dir}/uart.cpp" ]
@@ -268,6 +301,7 @@
sources += [
"${examples_plat_dir}/display/demo-ui.c",
"${examples_plat_dir}/display/lcd.cpp",
+ "src/ThermostatUI.cpp",
]
include_dirs += [ "${examples_plat_dir}/display" ]
defines += [
diff --git a/examples/thermostat/efr32/include/AppEvent.h b/examples/thermostat/efr32/include/AppEvent.h
index 7a19b71..d8d7de4 100644
--- a/examples/thermostat/efr32/include/AppEvent.h
+++ b/examples/thermostat/efr32/include/AppEvent.h
@@ -28,7 +28,6 @@
{
kEventType_Button = 0,
kEventType_Timer,
- kEventType_Light,
kEventType_Install,
};
@@ -44,11 +43,6 @@
{
void * Context;
} TimerEvent;
- struct
- {
- uint8_t Action;
- int32_t Actor;
- } LightEvent;
};
EventHandler Handler;
diff --git a/examples/thermostat/efr32/include/AppTask.h b/examples/thermostat/efr32/include/AppTask.h
index 800dda9..ce4fa6f 100644
--- a/examples/thermostat/efr32/include/AppTask.h
+++ b/examples/thermostat/efr32/include/AppTask.h
@@ -26,9 +26,15 @@
#include <stdbool.h>
#include <stdint.h>
+#ifdef DISPLAY_ENABLED
+#include "ThermostatUI.h"
+#endif
+
#include "AppEvent.h"
#include "BaseApplication.h"
#include "FreeRTOS.h"
+#include "SensorManager.h"
+#include "TemperatureManager.h"
#include "sl_simple_button_instances.h"
#include "timers.h" // provides FreeRTOS timer support
#include <app/clusters/identify-server/identify-server.h>
@@ -70,6 +76,11 @@
CHIP_ERROR StartAppTask();
/**
+ * @brief Request an update of the Thermostat LCD UI
+ */
+ void UpdateThermoStatUI();
+
+ /**
* @brief Event handler when a button is pressed
* Function posts an event for button processing
*
@@ -112,11 +123,5 @@
*/
static void ButtonHandler(AppEvent * aEvent);
- /**
- * @brief PB1 Button event processing function
- * Function triggers a thermostat action sent to the CHIP task
- *
- * @param aEvent button event being processed
- */
static void ThermostatActionEventHandler(AppEvent * aEvent);
};
diff --git a/examples/thermostat/efr32/include/CHIPProjectConfig.h b/examples/thermostat/efr32/include/CHIPProjectConfig.h
index 94c82dc..35f6d54 100644
--- a/examples/thermostat/efr32/include/CHIPProjectConfig.h
+++ b/examples/thermostat/efr32/include/CHIPProjectConfig.h
@@ -57,7 +57,7 @@
*
* 0x8005: example lighting app
*/
-#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8004
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x800E
/**
* CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION
@@ -98,6 +98,14 @@
#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC
+ *
+ * Enables synchronizing the device's real time clock with a remote Chip Time service
+ * using the Chip Time Sync protocol.
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIP_TIME_SERVICE_TIME_SYNC 0
+
+/**
* CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
*
* Enables the use of a hard-coded default serial number if none
diff --git a/examples/thermostat/efr32/include/SensorManager.h b/examples/thermostat/efr32/include/SensorManager.h
new file mode 100644
index 0000000..9c910ab
--- /dev/null
+++ b/examples/thermostat/efr32/include/SensorManager.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include <app-common/zap-generated/attributes/Accessors.h>
+#include <lib/core/CHIPError.h>
+
+class SensorManager
+{
+public:
+ CHIP_ERROR Init();
+
+private:
+ friend SensorManager & SensorMgr();
+
+ // Reads new generated sensor value, stores it, and updates local temperature attribute
+ static void SensorTimerEventHandler(TimerHandle_t xTimer);
+
+ static SensorManager sSensorManager;
+};
+
+inline SensorManager & SensorMgr()
+{
+ return SensorManager::sSensorManager;
+}
diff --git a/examples/thermostat/efr32/include/TemperatureManager.h b/examples/thermostat/efr32/include/TemperatureManager.h
new file mode 100644
index 0000000..1005a67
--- /dev/null
+++ b/examples/thermostat/efr32/include/TemperatureManager.h
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include <app-common/zap-generated/attributes/Accessors.h>
+
+#include <lib/core/CHIPError.h>
+
+using namespace chip;
+
+// AppCluster Spec Table 85.
+enum ThermMode
+{
+ OFF = 0,
+ AUTO,
+ NOT_USED,
+ COOL,
+ HEAT,
+};
+
+class TemperatureManager
+{
+public:
+ CHIP_ERROR Init();
+ void AttributeChangeHandler(EndpointId endpointId, AttributeId attributeId, uint8_t * value, uint16_t size);
+ uint8_t GetMode();
+ int8_t GetCurrentTemp();
+ int8_t GetHeatingSetPoint();
+ int8_t GetCoolingSetPoint();
+
+private:
+ friend TemperatureManager & TempMgr();
+
+ int8_t mCurrentTempCelsius;
+ int8_t mCoolingCelsiusSetPoint;
+ int8_t mHeatingCelsiusSetPoint;
+ uint8_t mThermMode;
+
+ int8_t ConvertToPrintableTemp(int16_t temperature);
+ static TemperatureManager sTempMgr;
+};
+
+inline TemperatureManager & TempMgr()
+{
+ return TemperatureManager::sTempMgr;
+}
diff --git a/examples/thermostat/efr32/include/ThermostatIcons.h b/examples/thermostat/efr32/include/ThermostatIcons.h
new file mode 100644
index 0000000..094775f
--- /dev/null
+++ b/examples/thermostat/efr32/include/ThermostatIcons.h
@@ -0,0 +1,218 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * 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.
+ */
+#pragma once
+
+#define SILABS_LOGO_WIDTH 47
+#define SILABS_LOGO_HEIGHT 18
+#define BLUETOOTH_ICON_SIZE 18
+
+// Status Icon defines
+#define STATUS_ICON_LINE 0
+#define SILABS_ICON_POSITION_X 0
+#define BLE_ICON_POSITION_X 72
+#define NETWORK_ICON_POSITION_X 90
+#define MATTER_ICON_POSITION_X 108
+
+// Heating/Cooling position
+#define HEATING_COOLING_X 90
+#define HEATING_COOLING_Y 40
+
+#define BLUETOOTH_ICON_SMALL \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x7F, 0xFE, 0xEF, 0xF1, 0x7F, 0x9F, 0xFF, 0x7B, 0xFF, 0x1F, 0xFE, 0xFF, 0xFC, 0xFF, \
+ 0xF3, 0xFF, 0x87, 0xFF, 0xEF, 0xFD, 0xDF, 0xE7, 0xBF, 0xC7, 0xFF, 0x9F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F
+
+#define SILABS_LOGO_SMALL \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, \
+ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0x9F, 0xFF, 0xE7, 0x3F, 0xE0, 0xF1, 0x83, \
+ 0xFF, 0xF9, 0xEF, 0xFF, 0x3F, 0xE0, 0x3F, 0xFC, 0xFF, 0xFF, 0x7F, 0xF8, 0x0F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFE, 0x03, 0xFC, \
+ 0xFF, 0xF7, 0x9F, 0xFF, 0x81, 0x07, 0x02, 0xF8, 0xFF, 0xFF, 0xE0, 0x07, 0x00, 0xFE, 0xFF, 0xFF, 0xF8, 0x03, 0xC0, 0xFF, \
+ 0xFF, 0xFF, 0xFE, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x3F
+
+#define HEATING_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFE, 0x7F, 0xFC, 0x1F, \
+ 0x1F, 0xF8, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0xBF, 0xC7, 0xE3, 0xFD, 0xFF, 0xE3, 0xC7, 0xFF, 0xFF, 0xF3, 0xCF, 0xFF, 0xFF, \
+ 0xF3, 0xCF, 0xFF, 0xFF, 0xF3, 0xCF, 0xFF, 0xFF, 0xF3, 0xCF, 0xFF, 0xFF, 0xE3, 0xC7, 0xFF, 0xBF, 0xC7, 0xE3, 0xFD, 0x3F, \
+ 0x07, 0xE0, 0xFC, 0x1F, 0x1F, 0xF8, 0xF8, 0x3F, 0xFE, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xBF, 0xFD, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#define HEATING_WIDTH 32
+#define HEATING_HEIGHT 32
+
+#define COOLING_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFD, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, \
+ 0x3F, 0xFC, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0x3F, 0x7F, 0xFE, 0xFC, 0x3F, 0x7F, 0xFE, 0xFC, 0x3F, \
+ 0x3E, 0x7C, 0xFC, 0x0F, 0x0C, 0x30, 0xF0, 0xCF, 0x80, 0x01, 0xF3, 0xFF, 0xE3, 0xC7, 0xFF, 0xFF, 0xF3, 0xCF, 0xFF, 0xFF, \
+ 0xF3, 0xCF, 0xFF, 0xFF, 0xF3, 0xCF, 0xFF, 0xFF, 0xF3, 0xCF, 0xFF, 0xFF, 0xE3, 0xC7, 0xFF, 0xCF, 0x80, 0x01, 0xF3, 0x0F, \
+ 0x0C, 0x30, 0xF0, 0x3F, 0x3E, 0x7C, 0xFC, 0x3F, 0x7F, 0xFE, 0xFC, 0x3F, 0x7F, 0xFE, 0xFC, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, \
+ 0x7F, 0xFE, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#define HEATING_COOLING_BITMAP \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, \
+ 0xFC, 0xE0, 0xFF, 0xFF, 0xFC, 0xF9, 0xF7, 0x7F, 0xFC, 0xF8, 0xF3, 0x1F, 0xFC, 0xFC, 0xF9, 0x1F, 0x78, 0xFC, 0xFC, 0xFF, \
+ 0x01, 0x7C, 0xFE, 0xFF, 0x03, 0x3C, 0xFF, 0xFF, 0xE3, 0x9F, 0xFF, 0xFF, 0xF3, 0x8F, 0xF3, 0xFF, 0xF3, 0x87, 0xE3, 0xFF, \
+ 0xF3, 0x83, 0xF7, 0xC7, 0xF0, 0x01, 0xF7, 0x07, 0xF0, 0x00, 0xFF, 0x0F, 0x7F, 0x00, 0xFF, 0xCF, 0x3F, 0x80, 0xFF, 0xCF, \
+ 0x1F, 0x80, 0xFF, 0xFF, 0x0F, 0xC0, 0xFF, 0xFF, 0x07, 0xE0, 0xFD, 0xFF, 0xF3, 0xF8, 0xFD, 0xFF, 0xF9, 0xFF, 0xFC, 0xFF, \
+ 0xFC, 0x3F, 0xFC, 0x7F, 0xDE, 0xFF, 0xFF, 0x3F, 0x1F, 0xFE, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#define COOLING_WIDTH 32
+#define COOLING_HEIGHT 32
+
+// Font for temperature
+#define CELSIUS_INDEX 2320
+#define FAHRENHEIT_INDEX 2370
+#define DEGREE_INDEX 2420
+
+#define MONACO_FONT_WIDTH 29
+#define MONACO_FONT_NB_LENGTH 232
+#define MONACO_FONT_CH_LENGTH 50
+
+#define MONACO_48PT \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFC, 0xFF, 0xFF, \
+ 0x00, 0xF0, 0xFF, 0x7F, 0x00, 0xC0, 0xFF, 0x3F, 0x00, 0x80, 0xFF, 0x1F, 0x60, 0x00, 0xFF, 0x1F, 0xF8, 0x03, 0xFF, 0x0F, \
+ 0xFC, 0x07, 0xFE, 0x07, 0xFE, 0x07, 0xFE, 0x07, 0xFE, 0x07, 0xFC, 0x07, 0xFF, 0x03, 0xFC, 0x03, 0xFF, 0x03, 0xFC, 0x03, \
+ 0xFF, 0x01, 0xF8, 0x83, 0xFF, 0x00, 0xF8, 0x83, 0xFF, 0x00, 0xF8, 0x83, 0x7F, 0x30, 0xF8, 0x83, 0x3F, 0x30, 0xF8, 0x83, \
+ 0x3F, 0x38, 0xF8, 0x81, 0x1F, 0x3C, 0xF8, 0x81, 0x0F, 0x3C, 0xF8, 0x81, 0x0F, 0x3E, 0xF8, 0x81, 0x07, 0x3E, 0xF8, 0x81, \
+ 0x07, 0x3F, 0xF8, 0x83, 0x83, 0x3F, 0xF8, 0x83, 0x81, 0x3F, 0xF8, 0x83, 0xC1, 0x3F, 0xF8, 0x83, 0xE0, 0x1F, 0xF8, 0x03, \
+ 0xE0, 0x1F, 0xF8, 0x03, 0xF0, 0x1F, 0xF8, 0x03, 0xF8, 0x1F, 0xFC, 0x07, 0xF8, 0x0F, 0xFC, 0x07, 0xFC, 0x0F, 0xFC, 0x07, \
+ 0xFC, 0x07, 0xFE, 0x0F, 0xFC, 0x07, 0xFE, 0x0F, 0xF8, 0x03, 0xFF, 0x1F, 0xE0, 0x00, 0xFF, 0x3F, 0x00, 0x80, 0xFF, 0x7F, \
+ 0x00, 0xC0, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0x03, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x30 (48: '0')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x07, 0xFC, 0xFF, 0xFF, 0x03, 0xFC, 0xFF, 0xFF, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0xFC, 0xFF, \
+ 0x1F, 0x00, 0xFC, 0xFF, 0x0F, 0x10, 0xFC, 0xFF, 0x0F, 0x1C, 0xFC, 0xFF, 0x0F, 0x1E, 0xFC, 0xFF, 0xCF, 0x1F, 0xFC, 0xFF, \
+ 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, \
+ 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, \
+ 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, \
+ 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, \
+ 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, \
+ 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x31 (49: '1')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, \
+ 0x3F, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0x80, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0xF8, 0x00, 0xFF, 0x0F, 0xFF, 0x03, 0xFE, \
+ 0xEF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, \
+ 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, \
+ 0xFF, 0x7F, 0xC0, 0xFF, 0xFF, 0x3F, 0xE0, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, 0xFF, 0x07, 0xFC, 0xFF, \
+ 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, \
+ 0x3F, 0xF0, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, \
+ 0x0F, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xFE, 0x07, 0x00, 0x00, 0xFC, 0x07, 0x00, 0x00, 0xFC, \
+ 0x07, 0x00, 0x00, 0xFC, 0x07, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x32 (50: '2')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, \
+ 0x0F, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x0F, 0x7C, 0x80, 0xFF, 0x8F, 0xFF, 0x01, 0xFF, \
+ 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, \
+ 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0x7F, 0xC0, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, \
+ 0x7F, 0x00, 0xF0, 0xFF, 0x7F, 0x00, 0xF8, 0xFF, 0x7F, 0x00, 0xE0, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, \
+ 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, \
+ 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, \
+ 0xFF, 0xFF, 0x07, 0xFE, 0xF7, 0xFF, 0x07, 0xFE, 0x87, 0xFF, 0x01, 0xFF, 0x07, 0x7C, 0x80, 0xFF, 0x07, 0x00, 0xC0, 0xFF, \
+ 0x07, 0x00, 0xE0, 0xFF, 0x0F, 0x00, 0xF0, 0xFF, 0x7F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x33 (51: '3')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x3F, 0xE0, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, \
+ 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x0F, 0xE0, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0x83, 0xE0, 0xFF, \
+ 0xFF, 0x81, 0xE0, 0xFF, 0xFF, 0xC0, 0xE0, 0xFF, 0xFF, 0xE0, 0xE0, 0xFF, 0x7F, 0xE0, 0xE0, 0xFF, 0x3F, 0xF0, 0xE0, 0xFF, \
+ 0x3F, 0xF8, 0xE0, 0xFF, 0x1F, 0xF8, 0xE0, 0xFF, 0x0F, 0xFC, 0xE0, 0xFF, 0x0F, 0xFE, 0xE0, 0xFF, 0x07, 0xFE, 0xE0, 0xFF, \
+ 0x03, 0xFF, 0xE0, 0xFF, 0x83, 0xFF, 0xE0, 0xFF, 0x81, 0xFF, 0xC0, 0xFF, 0x01, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0xF0, \
+ 0x01, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, \
+ 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, \
+ 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x34 (52: '4')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0x0F, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x00, 0xFE, \
+ 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, \
+ 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xC0, 0xFF, 0xFF, 0x0F, 0x00, 0xFC, 0xFF, \
+ 0x0F, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFE, \
+ 0xFF, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, \
+ 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, \
+ 0xFF, 0xFF, 0x07, 0xFE, 0xEF, 0xFF, 0x03, 0xFE, 0x07, 0xFF, 0x00, 0xFF, 0x07, 0x00, 0x80, 0xFF, 0x07, 0x00, 0xC0, 0xFF, \
+ 0x07, 0x00, 0xE0, 0xFF, 0x0F, 0x00, 0xF0, 0xFF, 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x35 (53: '5')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xC0, 0xFF, \
+ 0xFF, 0x07, 0x00, 0xFE, 0xFF, 0x01, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0xFE, 0x7F, 0x80, 0x07, 0xFE, 0x3F, 0xE0, 0x7F, 0xFE, \
+ 0x1F, 0xF0, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, \
+ 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x03, 0x0F, 0xE0, 0xFF, \
+ 0x83, 0x03, 0x80, 0xFF, 0x83, 0x01, 0x00, 0xFF, 0x83, 0x00, 0x00, 0xFE, 0x03, 0xC0, 0x07, 0xFC, 0x03, 0xF0, 0x0F, 0xFC, \
+ 0x03, 0xF8, 0x1F, 0xF8, 0x03, 0xFC, 0x3F, 0xF8, 0x03, 0xFC, 0x3F, 0xF8, 0x07, 0xFE, 0x3F, 0xF8, 0x07, 0xFE, 0x3F, 0xF8, \
+ 0x07, 0xFE, 0x3F, 0xF8, 0x07, 0xFE, 0x3F, 0xF8, 0x07, 0xFE, 0x3F, 0xF8, 0x0F, 0xFE, 0x3F, 0xF8, 0x0F, 0xFC, 0x1F, 0xF8, \
+ 0x0F, 0xFC, 0x1F, 0xFC, 0x1F, 0xF8, 0x0F, 0xFC, 0x1F, 0xF0, 0x07, 0xFE, 0x3F, 0xC0, 0x01, 0xFE, 0x7F, 0x00, 0x00, 0xFF, \
+ 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x01, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x36 (54: '6')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, \
+ 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x0F, 0xFE, \
+ 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, \
+ 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x3F, 0xF0, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, \
+ 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, \
+ 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, \
+ 0x7F, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x7F, 0xE0, 0xFF, 0xFF, 0x7F, 0xF0, 0xFF, 0xFF, \
+ 0x7F, 0xF0, 0xFF, 0xFF, 0x7F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x37 (55: '7')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0xFF, \
+ 0xFF, 0x01, 0xE0, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x3F, 0xE0, 0x00, 0xFF, 0x3F, 0xF8, 0x03, 0xFF, \
+ 0x1F, 0xFC, 0x07, 0xFE, 0x1F, 0xFC, 0x0F, 0xFE, 0x1F, 0xFC, 0x0F, 0xFE, 0x1F, 0xFC, 0x0F, 0xFE, 0x1F, 0xFC, 0x07, 0xFE, \
+ 0x1F, 0xF8, 0x07, 0xFF, 0x3F, 0xF0, 0x03, 0xFF, 0x3F, 0xE0, 0x81, 0xFF, 0x7F, 0xC0, 0x80, 0xFF, 0x7F, 0x00, 0xC0, 0xFF, \
+ 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0x01, 0xF0, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0x7F, 0x00, 0xC0, 0xFF, \
+ 0x3F, 0x60, 0x80, 0xFF, 0x1F, 0xF0, 0x00, 0xFF, 0x1F, 0xF8, 0x01, 0xFE, 0x0F, 0xFC, 0x03, 0xFE, 0x0F, 0xFC, 0x07, 0xFC, \
+ 0x07, 0xFE, 0x0F, 0xFC, 0x07, 0xFE, 0x0F, 0xFC, 0x07, 0xFF, 0x1F, 0xFC, 0x07, 0xFF, 0x1F, 0xFC, 0x07, 0xFF, 0x1F, 0xFC, \
+ 0x07, 0xFE, 0x0F, 0xFC, 0x07, 0xFC, 0x0F, 0xFC, 0x0F, 0xF8, 0x07, 0xFE, 0x0F, 0xE0, 0x01, 0xFE, 0x1F, 0x00, 0x00, 0xFF, \
+ 0x3F, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x38 (56: '8')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFE, 0xFF, \
+ 0xFF, 0x00, 0xF0, 0xFF, 0x3F, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0xC0, 0xFF, 0x0F, 0x70, 0x80, 0xFF, 0x07, 0xFC, 0x01, 0xFF, \
+ 0x07, 0xFE, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x83, 0xFF, 0x07, 0xFE, 0x83, 0xFF, 0x07, 0xFE, 0x83, 0xFF, 0x0F, 0xFC, \
+ 0xC1, 0xFF, 0x0F, 0xFC, 0xC1, 0xFF, 0x0F, 0xFC, 0xC1, 0xFF, 0x0F, 0xFC, 0x83, 0xFF, 0x07, 0xFC, 0x83, 0xFF, 0x07, 0xFC, \
+ 0x83, 0xFF, 0x07, 0xFC, 0x03, 0xFF, 0x03, 0xF8, 0x03, 0xFE, 0x01, 0xF8, 0x07, 0x7C, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF8, \
+ 0x1F, 0x00, 0x10, 0xF8, 0x3F, 0x00, 0x1C, 0xFC, 0xFF, 0x00, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x1F, 0xFC, \
+ 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, \
+ 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xCF, 0xFF, 0x80, 0xFF, 0x0F, 0x3E, 0xC0, 0xFF, 0x0F, 0x00, 0xE0, 0xFF, \
+ 0x0F, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0xFC, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x39 (57: '9')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0x1F, 0xE0, 0x0F, 0xE3, 0xC7, 0xFF, \
+ 0xE3, 0xFF, 0xE3, 0xFF, 0xE3, 0xFF, 0xE3, 0xFF, 0xE3, 0xFF, 0xE3, 0xFF, 0xC3, 0xFF, 0x87, 0xEF, 0x0F, 0xE0, 0x1F, 0xE0, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x63 (99: 'c')*/ \
+ 0xFF, 0xFB, 0x7F, 0xC0, 0x3F, 0xC0, 0x1F, 0xFF, 0x1F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x03, 0xF0, 0x03, 0xF0, \
+ 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x66 (102: 'f')*/ \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xDD, 0xFF, 0xE3, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* Character 0x20 (32: 'degree')*/
diff --git a/examples/thermostat/efr32/include/ThermostatUI.h b/examples/thermostat/efr32/include/ThermostatUI.h
new file mode 100644
index 0000000..671bbf8
--- /dev/null
+++ b/examples/thermostat/efr32/include/ThermostatUI.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * 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.
+ */
+
+#pragma once
+
+#include "ThermostatIcons.h"
+#include "glib.h"
+#include "lcd.h"
+
+class ThermostatUI
+{
+
+public:
+ // AppCluster Spec Table 85.
+ enum HVACMode
+ {
+ MODE_OFF = 0,
+ HEATING_COOLING,
+ NOT_USED,
+ COOLING,
+ HEATING,
+ };
+
+ static void DrawUI(GLIB_Context_t * glibContext);
+ static void SetHeatingSetPoint(int8_t temp);
+ static void SetCoolingSetPoint(int8_t temp);
+ static void SetCurrentTemp(int8_t temp);
+ static void SetMode(uint8_t mode);
+
+private:
+ static void DrawHeader(GLIB_Context_t * glibContext);
+ static void DrawFooter(GLIB_Context_t * glibContext, bool autoMode = true);
+ static void DrawCurrentTemp(GLIB_Context_t * glibContext, int8_t temp, bool isCelsius = true);
+ static void DrawFont(GLIB_Context_t * glibContext, uint8_t initial_x, uint8_t initial_y, uint8_t width, uint8_t * data,
+ uint32_t size);
+ static void DrawSetPoint(GLIB_Context_t * glibContext, int8_t setPoint, bool secondLine);
+};
diff --git a/examples/thermostat/efr32/src/AppTask.cpp b/examples/thermostat/efr32/src/AppTask.cpp
index 37ab028..64af085 100644
--- a/examples/thermostat/efr32/src/AppTask.cpp
+++ b/examples/thermostat/efr32/src/AppTask.cpp
@@ -31,6 +31,7 @@
#endif // ENABLE_WSTK_LEDS
#ifdef DISPLAY_ENABLED
+#include "ThermostatUI.h"
#include "lcd.h"
#ifdef QR_CODE_ENABLED
#include "qrcodegen.h"
@@ -39,7 +40,13 @@
#include <app-common/zap-generated/attribute-id.h>
#include <app-common/zap-generated/attribute-type.h>
+#include <app-common/zap-generated/attributes/Accessors.h>
+#include <app-common/zap-generated/callback.h>
#include <app-common/zap-generated/cluster-id.h>
+#include <app-common/zap-generated/cluster-objects.h>
+#include <app-common/zap-generated/command-id.h>
+#include <app-common/zap-generated/enums.h>
+#include <app-common/zap-generated/ids/Attributes.h>
#include <app/server/OnboardingCodesUtil.h>
#include <app/server/Server.h>
#include <app/util/attribute-storage.h>
@@ -56,7 +63,10 @@
#define APP_FUNCTION_BUTTON &sl_button_btn0
#define APP_THERMOSTAT &sl_button_btn1
+#define MODE_TIMER 1000 // 1s timer period
+
using namespace chip;
+using namespace chip::TLV;
using namespace ::chip::DeviceLayer;
/**********************************************************
@@ -129,9 +139,6 @@
} // namespace
-using namespace chip::TLV;
-using namespace ::chip::DeviceLayer;
-
/**********************************************************
* AppTask Definitions
*********************************************************/
@@ -144,6 +151,7 @@
#ifdef DISPLAY_ENABLED
GetLCD().Init((uint8_t *) "Thermostat-App");
+ GetLCD().SetCustomUI(ThermostatUI::DrawUI);
#endif
err = BaseApplication::Init(&gIdentify);
@@ -152,6 +160,18 @@
EFR32_LOG("BaseApplication::Init() failed");
appError(err);
}
+ err = SensorMgr().Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ EFR32_LOG("SensorMgr::Init() failed");
+ appError(err);
+ }
+ err = TempMgr().Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ EFR32_LOG("TempMgr::Init() failed");
+ appError(err);
+ }
return err;
}
@@ -207,34 +227,42 @@
#endif
}
-void AppTask::ThermostatActionEventHandler(AppEvent * aEvent)
+void AppTask::UpdateThermoStatUI()
{
- if (aEvent->Type == AppEvent::kEventType_Button)
+#ifdef DISPLAY_ENABLED
+ ThermostatUI::SetMode(TempMgr().GetMode());
+ ThermostatUI::SetHeatingSetPoint(TempMgr().GetHeatingSetPoint());
+ ThermostatUI::SetCoolingSetPoint(TempMgr().GetCoolingSetPoint());
+ ThermostatUI::SetCurrentTemp(TempMgr().GetCurrentTemp());
+
+#ifdef SL_WIFI
+ if (ConnectivityMgr().IsWiFiStationProvisioned())
+#else
+ if (ConnectivityMgr().IsThreadProvisioned())
+#endif /* !SL_WIFI */
{
- EFR32_LOG("App Button was pressed!");
- // TODO: Implement button functionnality
+ AppTask::GetAppTask().GetLCD().WriteDemoUI(false); // State doesn't Matter
}
+#else
+ EFR32_LOG("Thermostat Status - M:%d T:%d'C H:%d'C C:%d'C", TempMgr().GetMode(), TempMgr().GetCurrentTemp(),
+ TempMgr().GetHeatingSetPoint(), TempMgr().GetCoolingSetPoint());
+#endif // DISPLAY_ENABLED
}
void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction)
{
- if (buttonHandle == NULL)
+ if (buttonHandle == nullptr)
{
return;
}
- AppEvent button_event = {};
- button_event.Type = AppEvent::kEventType_Button;
- button_event.ButtonEvent.Action = btnAction;
+ AppEvent aEvent = {};
+ aEvent.Type = AppEvent::kEventType_Button;
+ aEvent.ButtonEvent.Action = btnAction;
- if (buttonHandle == APP_THERMOSTAT && btnAction == SL_SIMPLE_BUTTON_PRESSED)
+ if (buttonHandle == APP_FUNCTION_BUTTON)
{
- button_event.Handler = ThermostatActionEventHandler;
- sAppTask.PostEvent(&button_event);
- }
- else if (buttonHandle == APP_FUNCTION_BUTTON)
- {
- button_event.Handler = BaseApplication::ButtonHandler;
- sAppTask.PostEvent(&button_event);
+ aEvent.Handler = BaseApplication::ButtonHandler;
+ sAppTask.PostEvent(&aEvent);
}
}
diff --git a/examples/thermostat/efr32/src/SensorManager.cpp b/examples/thermostat/efr32/src/SensorManager.cpp
new file mode 100644
index 0000000..4a60846
--- /dev/null
+++ b/examples/thermostat/efr32/src/SensorManager.cpp
@@ -0,0 +1,133 @@
+/*
+ *
+ * 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.
+ */
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include "SensorManager.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+#include "AppTask.h"
+
+#ifdef USE_TEMP_SENSOR
+#include "TemperatureSensor.h"
+#endif
+/**********************************************************
+ * Defines and Constants
+ *********************************************************/
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+constexpr EndpointId kThermostatEndpoint = 1;
+constexpr uint16_t kSensorTImerPeriodMs = 30000; // 30s timer period
+constexpr uint16_t kMinTemperatureDelta = 50; // 0.5 degree Celcius
+
+/**********************************************************
+ * Variable declarations
+ *********************************************************/
+
+TimerHandle_t sSensorTimer;
+StaticTimer_t sStaticSensorTimerStruct;
+
+SensorManager SensorManager::sSensorManager;
+
+#ifndef USE_TEMP_SENSOR
+constexpr uint16_t kSimulatedReadingFrequency = (60000 / kSensorTImerPeriodMs); // Change Simulated number at each minutes
+static int16_t mSimulatedTemp[] = { 2300, 2400, 2800, 2550, 2200, 2125, 2100, 2600, 1800, 2700 };
+#endif
+
+CHIP_ERROR SensorManager::Init()
+{
+ // Create FreeRTOS sw timer for temp sensor timer.
+ sSensorTimer = xTimerCreateStatic("sensorTmr", pdMS_TO_TICKS(kSensorTImerPeriodMs), true, nullptr, SensorTimerEventHandler,
+ &sStaticSensorTimerStruct);
+
+ if (sSensorTimer == NULL)
+ {
+ EFR32_LOG("sSensorTimer timer create failed");
+ return APP_ERROR_CREATE_TIMER_FAILED;
+ }
+
+#ifdef USE_TEMP_SENSOR
+ if (SL_STATUS_OK != TemperatureSensor::Init())
+ {
+ EFR32_LOG("Failed to Init Sensor");
+ return CHIP_ERROR_INTERNAL;
+ }
+#endif
+
+ // Update Temp immediatly at bootup
+ SensorTimerEventHandler(sSensorTimer);
+
+ // Trigger periodic update
+ xTimerStart(sSensorTimer, portMAX_DELAY);
+
+ return CHIP_NO_ERROR;
+}
+
+void SensorManager::SensorTimerEventHandler(TimerHandle_t xTimer)
+{
+ int16_t temperature = 0;
+ static int16_t lastTemperature = 0;
+
+#ifdef USE_TEMP_SENSOR
+ int32_t tempSum = 0;
+ uint32_t humidity = 0;
+
+ for (uint8_t i = 0; i < 100; i++)
+ {
+ if (SL_STATUS_OK != TemperatureSensor::GetTemp(&humidity, &temperature))
+ {
+ EFR32_LOG("Failed to read Temperature !!!");
+ }
+ tempSum += temperature;
+ }
+ temperature = static_cast<int16_t>(tempSum / 100);
+#else
+ static uint8_t nbOfRepetition = 0;
+ static uint8_t simulatedIndex = 0;
+ if (simulatedIndex >= sizeof(mSimulatedTemp))
+ {
+ simulatedIndex = 0;
+ }
+ temperature = mSimulatedTemp[simulatedIndex];
+
+ nbOfRepetition++;
+ if (nbOfRepetition >= kSimulatedReadingFrequency)
+ {
+ simulatedIndex++;
+ nbOfRepetition = 0;
+ }
+#endif // USE_TEMP_SENSOR
+
+ EFR32_LOG("Sensor Temp is : %d", temperature);
+
+ if ((temperature >= (lastTemperature + kMinTemperatureDelta)) || temperature <= (lastTemperature - kMinTemperatureDelta))
+ {
+ lastTemperature = temperature;
+ PlatformMgr().LockChipStack();
+ // The SensorMagager shouldn't be aware of the Endpoint ID TODO Fix this.
+ // TODO Per Spec we should also apply the Offset stored in the same cluster before saving the temp
+
+ app::Clusters::Thermostat::Attributes::LocalTemperature::Set(kThermostatEndpoint, temperature);
+ PlatformMgr().UnlockChipStack();
+ }
+}
diff --git a/examples/thermostat/efr32/src/TemperatureManager.cpp b/examples/thermostat/efr32/src/TemperatureManager.cpp
new file mode 100644
index 0000000..8b0d6c7
--- /dev/null
+++ b/examples/thermostat/efr32/src/TemperatureManager.cpp
@@ -0,0 +1,149 @@
+/*
+ *
+ * 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.
+ */
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include "TemperatureManager.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+#include "AppTask.h"
+#include "semphr.h"
+
+/**********************************************************
+ * Defines and Constants
+ *********************************************************/
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+constexpr EndpointId kThermostatEndpoint = 1;
+
+namespace ThermAttr = chip::app::Clusters::Thermostat::Attributes;
+/**********************************************************
+ * Variable declarations
+ *********************************************************/
+
+TemperatureManager TemperatureManager::sTempMgr;
+
+CHIP_ERROR TemperatureManager::Init()
+{
+ app::DataModel::Nullable<int16_t> temp;
+ int16_t heatingSetpoint, coolingSetpoint;
+ uint8_t systemMode;
+
+ PlatformMgr().LockChipStack();
+ ThermAttr::LocalTemperature::Get(kThermostatEndpoint, temp);
+ ThermAttr::OccupiedCoolingSetpoint::Get(kThermostatEndpoint, &coolingSetpoint);
+ ThermAttr::OccupiedHeatingSetpoint::Get(kThermostatEndpoint, &heatingSetpoint);
+ ThermAttr::SystemMode::Get(kThermostatEndpoint, &systemMode);
+ PlatformMgr().UnlockChipStack();
+
+ mCurrentTempCelsius = ConvertToPrintableTemp(temp.Value());
+ mHeatingCelsiusSetPoint = ConvertToPrintableTemp(coolingSetpoint);
+ mCoolingCelsiusSetPoint = ConvertToPrintableTemp(heatingSetpoint);
+ mThermMode = systemMode;
+
+ AppTask::GetAppTask().UpdateThermoStatUI();
+
+ return CHIP_NO_ERROR;
+}
+
+int8_t TemperatureManager::ConvertToPrintableTemp(int16_t temperature)
+{
+ constexpr uint8_t kRoundUpValue = 50;
+
+ // Round up the temperature as we won't print decimals on LCD
+ // Is it a negative temperature
+ if (temperature < 0)
+ {
+ temperature -= kRoundUpValue;
+ }
+ else
+ {
+ temperature += kRoundUpValue;
+ }
+
+ return static_cast<int8_t>(temperature / 100);
+}
+
+void TemperatureManager::AttributeChangeHandler(EndpointId endpointId, AttributeId attributeId, uint8_t * value, uint16_t size)
+{
+ switch (attributeId)
+ {
+ case ThermAttr::LocalTemperature::Id: {
+ int8_t Temp = ConvertToPrintableTemp(*((int16_t *) value));
+ EFR32_LOG("Local temp %d", Temp);
+ mCurrentTempCelsius = Temp;
+ }
+ break;
+
+ case ThermAttr::OccupiedCoolingSetpoint::Id: {
+ int8_t coolingTemp = ConvertToPrintableTemp(*((int16_t *) value));
+ EFR32_LOG("CoolingSetpoint %d", coolingTemp);
+ mCoolingCelsiusSetPoint = coolingTemp;
+ }
+ break;
+
+ case ThermAttr::OccupiedHeatingSetpoint::Id: {
+ int8_t heatingTemp = ConvertToPrintableTemp(*((int16_t *) value));
+ EFR32_LOG("HeatingSetpoint %d", heatingTemp);
+ mHeatingCelsiusSetPoint = heatingTemp;
+ }
+ break;
+
+ case ThermAttr::SystemMode::Id: {
+ EFR32_LOG("SystemMode %d", static_cast<uint8_t>(*value));
+ uint8_t mode = static_cast<uint8_t>(*value);
+ if (mThermMode != mode)
+ {
+ mThermMode = mode;
+ }
+ }
+ break;
+
+ default: {
+ EFR32_LOG("Unhandled thermostat attribute %x", attributeId);
+ return;
+ }
+ break;
+ }
+
+ AppTask::GetAppTask().UpdateThermoStatUI();
+}
+
+uint8_t TemperatureManager::GetMode()
+{
+ return mThermMode;
+}
+
+int8_t TemperatureManager::GetCurrentTemp()
+{
+ return mCurrentTempCelsius;
+}
+int8_t TemperatureManager::GetHeatingSetPoint()
+{
+ return mHeatingCelsiusSetPoint;
+}
+
+int8_t TemperatureManager::GetCoolingSetPoint()
+{
+ return mCoolingCelsiusSetPoint;
+}
diff --git a/examples/thermostat/efr32/src/ThermostatUI.cpp b/examples/thermostat/efr32/src/ThermostatUI.cpp
new file mode 100644
index 0000000..9336d35
--- /dev/null
+++ b/examples/thermostat/efr32/src/ThermostatUI.cpp
@@ -0,0 +1,255 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * 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 <stdio.h>
+#include <string.h>
+
+#include "ThermostatUI.h"
+#include "demo-ui-bitmaps.h"
+#include "dmd.h"
+#include "glib.h"
+#include "lcd.h"
+
+// LCD line define
+constexpr uint8_t kTempLcdInitialX = 30;
+
+// Bitmap
+static const uint8_t silabsLogo[] = { SILABS_LOGO_SMALL };
+static const uint8_t matterLogoBitmap[] = { MATTER_LOGO_BITMAP };
+
+static const uint8_t wifiLogo[] = { WIFI_BITMAP };
+static const uint8_t threadLogo[] = { THREAD_BITMAP };
+static const uint8_t bleLogo[] = { BLUETOOTH_ICON_SMALL };
+
+static const unsigned char monaco_48pt[] = { MONACO_48PT };
+static const unsigned char heating_bits[] = { HEATING_BITMAP };
+static const unsigned char cooling_bits[] = { COOLING_BITMAP };
+static const unsigned char heating_cooling_bits[] = { HEATING_COOLING_BITMAP };
+
+static int8_t mHeatingCelsiusSetPoint;
+static int8_t mCoolingCelsiusSetPoint;
+static int8_t mCurrentTempCelsius;
+static uint8_t mMode;
+
+#ifdef SL_WIFI
+#define UI_WIFI 1
+#else
+#define UI_WIFI 0
+#endif
+
+void ThermostatUI::DrawUI(GLIB_Context_t * glibContext)
+{
+ if (glibContext == nullptr)
+ {
+ EFR32_LOG("Context is null");
+ return;
+ }
+
+ GLIB_clear(glibContext);
+ DrawHeader(glibContext);
+ DrawCurrentTemp(glibContext, mCurrentTempCelsius);
+ DrawFooter(glibContext, false);
+
+ DMD_updateDisplay();
+}
+
+void ThermostatUI::SetHeatingSetPoint(int8_t temp)
+{
+ mHeatingCelsiusSetPoint = temp;
+}
+
+void ThermostatUI::SetCoolingSetPoint(int8_t temp)
+{
+ mCoolingCelsiusSetPoint = temp;
+}
+
+void ThermostatUI::SetCurrentTemp(int8_t temp)
+{
+ mCurrentTempCelsius = temp;
+}
+void ThermostatUI::SetMode(uint8_t mode)
+{
+ mMode = mode;
+}
+
+void ThermostatUI::DrawHeader(GLIB_Context_t * glibContext)
+{
+ // Draw Silabs Corner icon
+ GLIB_drawBitmap(glibContext, SILABS_ICON_POSITION_X, STATUS_ICON_LINE, SILABS_LOGO_WIDTH, SILABS_LOGO_HEIGHT, silabsLogo);
+ // Draw BLE Icon
+ GLIB_drawBitmap(glibContext, BLE_ICON_POSITION_X, STATUS_ICON_LINE, BLUETOOTH_ICON_SIZE, BLUETOOTH_ICON_SIZE, bleLogo);
+ // Draw WiFi/OpenThread Icon
+ GLIB_drawBitmap(glibContext, NETWORK_ICON_POSITION_X, STATUS_ICON_LINE, (UI_WIFI) ? WIFI_BITMAP_HEIGHT : THREAD_BITMAP_WIDTH,
+ WIFI_BITMAP_HEIGHT, (UI_WIFI) ? wifiLogo : threadLogo);
+ // Draw Matter Icon
+ GLIB_drawBitmap(glibContext, MATTER_ICON_POSITION_X, STATUS_ICON_LINE, MATTER_LOGO_WIDTH, MATTER_LOGO_HEIGHT, matterLogoBitmap);
+ DMD_updateDisplay();
+}
+
+void ThermostatUI::DrawFooter(GLIB_Context_t * glibContext, bool autoMode)
+{
+ switch (static_cast<ThermostatUI::HVACMode>(mMode))
+ {
+ case HVACMode::HEATING:
+ GLIB_drawStringOnLine(glibContext, "Mode : Heating", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+ GLIB_drawBitmap(glibContext, HEATING_COOLING_X, HEATING_COOLING_Y, COOLING_WIDTH, COOLING_HEIGHT, heating_bits);
+ DrawSetPoint(glibContext, mHeatingCelsiusSetPoint, false);
+ break;
+ case HVACMode::COOLING:
+ GLIB_drawStringOnLine(glibContext, "Mode : Cooling", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+ GLIB_drawBitmap(glibContext, HEATING_COOLING_X, HEATING_COOLING_Y, COOLING_WIDTH, COOLING_HEIGHT, cooling_bits);
+ DrawSetPoint(glibContext, mCoolingCelsiusSetPoint, false);
+ break;
+ case HVACMode::HEATING_COOLING:
+ GLIB_drawStringOnLine(glibContext, "Mode : Auto", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+ GLIB_drawBitmap(glibContext, HEATING_COOLING_X, HEATING_COOLING_Y, COOLING_WIDTH, COOLING_HEIGHT, heating_cooling_bits);
+ DrawSetPoint(glibContext, mHeatingCelsiusSetPoint, false);
+ DrawSetPoint(glibContext, mCoolingCelsiusSetPoint, true);
+ break;
+ case HVACMode::MODE_OFF:
+ DrawSetPoint(glibContext, 0, false);
+ GLIB_drawStringOnLine(glibContext, "Mode : OFF", 11, GLIB_ALIGN_LEFT, 0, 0, true);
+ break;
+ default:
+ break;
+ }
+
+ DMD_updateDisplay();
+}
+
+/**
+ * @brief Draw a 2 digit Temp of screen. Because of this Celsius is used by default
+ * @param GLIB_Context_t * pointer to the context for the GLIB library
+ * @param int8_t current Temperature in Celsius
+ * @param int8_t setPoint in Celsius
+ * @param bool isCelsius By default set to True. For future development
+ */
+void ThermostatUI::DrawCurrentTemp(GLIB_Context_t * glibContext, int8_t temp, bool isCelsius)
+{
+ uint8_t tempArray[2];
+ uint8_t position_x = 10;
+ uint8_t * data;
+
+ if (temp > 99 || temp < -99)
+ {
+ // Invalid temp for a house thermostat
+ return;
+ }
+
+ if (temp < 0)
+ {
+ for (uint8_t y = 60; y < 64; y++)
+ {
+ for (uint8_t x = 1; x < 10; x++)
+ {
+ GLIB_drawPixel(glibContext, x, y);
+ }
+ }
+
+ temp = temp * -1;
+ }
+
+ // Draw Unit
+ if (isCelsius)
+ {
+ data = (uint8_t *) &monaco_48pt[DEGREE_INDEX];
+ DrawFont(glibContext, 65, kTempLcdInitialX, 15, data, MONACO_FONT_CH_LENGTH);
+ data = (uint8_t *) &monaco_48pt[CELSIUS_INDEX];
+ DrawFont(glibContext, 70, kTempLcdInitialX, 15, data, MONACO_FONT_CH_LENGTH);
+ }
+ else
+ {
+ data = (uint8_t *) &monaco_48pt[DEGREE_INDEX];
+ DrawFont(glibContext, 65, 25, 15, data, MONACO_FONT_CH_LENGTH); // 25 to fit with f of fahrenheint
+ data = (uint8_t *) &monaco_48pt[FAHRENHEIT_INDEX];
+ DrawFont(glibContext, 70, kTempLcdInitialX, 15, data, MONACO_FONT_CH_LENGTH);
+ }
+
+ // Print Current temp
+ tempArray[0] = (uint8_t)((temp / 10));
+ tempArray[1] = (uint8_t)((temp % 10));
+
+ for (uint8_t ch = 0; ch < 2; ch++)
+ {
+ data = (uint8_t *) &monaco_48pt[tempArray[ch] * MONACO_FONT_NB_LENGTH];
+ DrawFont(glibContext, position_x, kTempLcdInitialX, MONACO_FONT_WIDTH, data, MONACO_FONT_NB_LENGTH);
+ position_x += MONACO_FONT_WIDTH;
+ }
+}
+
+void ThermostatUI::DrawFont(GLIB_Context_t * glibContext, uint8_t initial_x, uint8_t initial_y, uint8_t width, uint8_t * data,
+ uint32_t size)
+{
+ uint8_t x = initial_x, y = initial_y;
+ for (uint16_t i = 0; i < size; i++)
+ {
+ for (uint8_t mask = 0; mask < 8; mask++)
+ {
+ if (!(data[i] & (0x01 << mask)))
+ {
+ GLIB_drawPixel(glibContext, x, y);
+ }
+ // Check line changes
+ if (((x - initial_x) % width) == 0 && x != initial_x)
+ {
+ x = initial_x;
+ y++;
+ // Font is 8 bit align with paddings bits;
+ mask = 8;
+ }
+ else
+ {
+ x++;
+ }
+ }
+ }
+}
+
+void ThermostatUI::DrawSetPoint(GLIB_Context_t * glibContext, int8_t setPoint, bool secondLine)
+{
+ char setPointLine[] = { '-', 'X', 'X', '\0' };
+
+ if (setPoint > 99 || setPoint < -99)
+ {
+ return;
+ }
+
+ // Update SetPoint string
+ if (static_cast<ThermostatUI::HVACMode>(mMode) == ThermostatUI::HVACMode::MODE_OFF)
+ {
+ setPointLine[0] = '-';
+ setPointLine[1] = '-';
+ setPointLine[2] = '\0';
+ }
+ else if (setPoint < 0)
+ {
+ setPointLine[0] = (setPoint < 0) ? '-' : ' ';
+ setPoint *= -1;
+ setPointLine[1] = ((setPoint / 10) + 0x30);
+ setPointLine[2] = ((setPoint % 10) + 0x30);
+ }
+ else
+ {
+ setPointLine[0] = ((setPoint / 10) + 0x30);
+ setPointLine[1] = ((setPoint % 10) + 0x30);
+ setPointLine[2] = '\0';
+ }
+
+ // Print SetPoint
+ GLIB_drawStringOnLine(glibContext, setPointLine, (secondLine) ? 8 : 7, GLIB_ALIGN_LEFT, 67, 0, true);
+}
diff --git a/examples/thermostat/efr32/src/ZclCallbacks.cpp b/examples/thermostat/efr32/src/ZclCallbacks.cpp
index f89d4aa..734637d 100644
--- a/examples/thermostat/efr32/src/ZclCallbacks.cpp
+++ b/examples/thermostat/efr32/src/ZclCallbacks.cpp
@@ -22,6 +22,7 @@
#include "AppConfig.h"
+#include "TemperatureManager.h"
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/ConcreteAttributePath.h>
@@ -42,24 +43,8 @@
ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
ChipLogValueMEI(attributeId), type, *value, size);
}
-}
-
-/** @brief OnOff Cluster Init
- *
- * This function is called when a specific cluster is initialized. It gives the
- * application an opportunity to take care of cluster initialization procedures.
- * It is called exactly once for each endpoint where cluster is present.
- *
- * @param endpoint Ver.: always
- *
- * TODO Issue #3841
- * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster
- * attributes to the default value.
- * The logic here expects something similar to the deprecated Plugins callback
- * emberAfPluginOnOffClusterServerPostInitCallback.
- *
- */
-void emberAfOnOffClusterInitCallback(EndpointId endpoint)
-{
- // TODO: implement any additional Cluster Server init actions
+ else if (clusterId == Thermostat::Id)
+ {
+ TempMgr().AttributeChangeHandler(attributePath.mEndpointId, attributeId, value, size);
+ }
}
diff --git a/examples/thermostat/thermostat-common/thermostat.matter b/examples/thermostat/thermostat-common/thermostat.matter
index 9b104b9..15933ed 100644
--- a/examples/thermostat/thermostat-common/thermostat.matter
+++ b/examples/thermostat/thermostat-common/thermostat.matter
@@ -1436,6 +1436,16 @@
command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0;
}
+server cluster ThermostatUserInterfaceConfiguration = 516 {
+ attribute enum8 temperatureDisplayMode = 0;
+ attribute access(write: manage) enum8 keypadLockout = 1;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+}
+
endpoint 0 {
device type rootdevice = 22;
binding cluster OtaSoftwareUpdateProvider;
@@ -1743,29 +1753,13 @@
ram attribute clusterRevision default = 4;
}
- server cluster Basic {
- callback attribute dataModelRevision default = 10;
- callback attribute vendorName;
- callback attribute vendorID;
- callback attribute productName;
- callback attribute productID;
- persist attribute nodeLabel;
- callback attribute location default = "XX";
- callback attribute hardwareVersion;
- callback attribute hardwareVersionString;
- callback attribute softwareVersion;
- callback attribute softwareVersionString;
- callback attribute manufacturingDate default = "20210614123456ZZ";
- callback attribute partNumber;
- callback attribute productURL;
- callback attribute productLabel;
- callback attribute serialNumber;
- persist attribute localConfigDisabled;
- ram attribute reachable default = 1;
- callback attribute uniqueID;
- callback attribute capabilityMinima;
+ server cluster Descriptor {
+ callback attribute deviceTypeList;
+ callback attribute serverList;
+ callback attribute clientList;
+ callback attribute partsList;
ram attribute featureMap;
- ram attribute clusterRevision default = 1;
+ callback attribute clusterRevision default = 1;
}
server cluster Thermostat {
@@ -1774,21 +1768,31 @@
ram attribute absMaxHeatSetpointLimit default = 3000;
ram attribute absMinCoolSetpointLimit default = 1600;
ram attribute absMaxCoolSetpointLimit default = 3200;
- ram attribute occupiedCoolingSetpoint default = 0x0A28;
- ram attribute occupiedHeatingSetpoint default = 0x07D0;
+ persist attribute occupiedCoolingSetpoint default = 0x0A28;
+ persist attribute occupiedHeatingSetpoint default = 0x07D0;
ram attribute minHeatSetpointLimit default = 700;
ram attribute maxHeatSetpointLimit default = 3000;
ram attribute minCoolSetpointLimit default = 1600;
ram attribute maxCoolSetpointLimit default = 3200;
ram attribute minSetpointDeadBand default = 0x19;
ram attribute controlSequenceOfOperation default = 0x04;
- ram attribute systemMode default = 0x01;
+ persist attribute systemMode default = 0x01;
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute attributeList;
ram attribute featureMap default = 0x23;
ram attribute clusterRevision default = 5;
}
+
+ server cluster ThermostatUserInterfaceConfiguration {
+ ram attribute temperatureDisplayMode;
+ ram attribute keypadLockout;
+ callback attribute generatedCommandList;
+ callback attribute acceptedCommandList;
+ callback attribute attributeList;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
}
diff --git a/examples/thermostat/thermostat-common/thermostat.zap b/examples/thermostat/thermostat-common/thermostat.zap
index 601a871..ca91d4a 100644
--- a/examples/thermostat/thermostat-common/thermostat.zap
+++ b/examples/thermostat/thermostat-common/thermostat.zap
@@ -1,5 +1,5 @@
{
- "featureLevel": 81,
+ "featureLevel": 85,
"creator": "zap",
"keyValuePairs": [
{
@@ -8592,7 +8592,7 @@
"mfgCode": null,
"define": "DESCRIPTOR_CLUSTER",
"side": "server",
- "enabled": 0,
+ "enabled": 1,
"attributes": [
{
"name": "DeviceTypeList",
@@ -8659,6 +8659,22 @@
"reportableChange": 0
},
{
+ "name": "FeatureMap",
+ "code": 65532,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap32",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
"name": "ClusterRevision",
"code": 65533,
"mfgCode": null,
@@ -8776,7 +8792,7 @@
"mfgCode": null,
"define": "BASIC_CLUSTER",
"side": "server",
- "enabled": 1,
+ "enabled": 0,
"attributes": [
{
"name": "DataModelRevision",
@@ -11119,7 +11135,7 @@
"side": "server",
"type": "int16s",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "NVM",
"singleton": 0,
"bounded": 0,
"defaultValue": "0x0A28",
@@ -11135,7 +11151,7 @@
"side": "server",
"type": "int16s",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "NVM",
"singleton": 0,
"bounded": 0,
"defaultValue": "0x07D0",
@@ -11247,7 +11263,7 @@
"side": "server",
"type": "enum8",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "NVM",
"singleton": 0,
"bounded": 0,
"defaultValue": "0x01",
@@ -11387,6 +11403,186 @@
]
},
{
+ "name": "Thermostat User Interface Configuration",
+ "code": 516,
+ "mfgCode": null,
+ "define": "THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "FeatureMap",
+ "code": 65532,
+ "mfgCode": null,
+ "side": "client",
+ "type": "bitmap32",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Thermostat User Interface Configuration",
+ "code": 516,
+ "mfgCode": null,
+ "define": "THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "temperature display mode",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "enum8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "keypad lockout",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "enum8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "schedule programming visibility",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "enum8",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "GeneratedCommandList",
+ "code": 65528,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AcceptedCommandList",
+ "code": 65529,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AttributeList",
+ "code": 65531,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "FeatureMap",
+ "code": 65532,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap32",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
"name": "Color Control",
"code": 768,
"mfgCode": null,
@@ -14354,5 +14550,6 @@
"endpointVersion": 1,
"deviceIdentifier": 769
}
- ]
+ ],
+ "log": []
}
\ No newline at end of file
diff --git a/zzz_generated/thermostat/zap-generated/access.h b/zzz_generated/thermostat/zap-generated/access.h
index 8babb2f..794789b 100644
--- a/zzz_generated/thermostat/zap-generated/access.h
+++ b/zzz_generated/thermostat/zap-generated/access.h
@@ -54,6 +54,7 @@
/* Cluster: Thermostat, Attribute: MinSetpointDeadBand, Privilege: view */ \
/* Cluster: Thermostat, Attribute: ControlSequenceOfOperation, Privilege: view */ \
/* Cluster: Thermostat, Attribute: SystemMode, Privilege: view */ \
+ /* Cluster: Thermostat User Interface Configuration, Attribute: keypad lockout, Privilege: view */ \
}
// Parallel array data (cluster, *attribute*, privilege) for read attribute
@@ -83,6 +84,7 @@
/* Cluster: Thermostat, Attribute: MinSetpointDeadBand, Privilege: view */ \
/* Cluster: Thermostat, Attribute: ControlSequenceOfOperation, Privilege: view */ \
/* Cluster: Thermostat, Attribute: SystemMode, Privilege: view */ \
+ /* Cluster: Thermostat User Interface Configuration, Attribute: keypad lockout, Privilege: view */ \
}
// Parallel array data (cluster, attribute, *privilege*) for read attribute
@@ -112,6 +114,7 @@
/* Cluster: Thermostat, Attribute: MinSetpointDeadBand, Privilege: view */ \
/* Cluster: Thermostat, Attribute: ControlSequenceOfOperation, Privilege: view */ \
/* Cluster: Thermostat, Attribute: SystemMode, Privilege: view */ \
+ /* Cluster: Thermostat User Interface Configuration, Attribute: keypad lockout, Privilege: view */ \
}
////////////////////////////////////////////////////////////////////////////////
@@ -134,6 +137,7 @@
513, /* Cluster: Thermostat, Attribute: MinSetpointDeadBand, Privilege: manage */ \
513, /* Cluster: Thermostat, Attribute: ControlSequenceOfOperation, Privilege: manage */ \
513, /* Cluster: Thermostat, Attribute: SystemMode, Privilege: manage */ \
+ 516, /* Cluster: Thermostat User Interface Configuration, Attribute: keypad lockout, Privilege: manage */ \
}
// Parallel array data (cluster, *attribute*, privilege) for write attribute
@@ -154,6 +158,7 @@
25, /* Cluster: Thermostat, Attribute: MinSetpointDeadBand, Privilege: manage */ \
27, /* Cluster: Thermostat, Attribute: ControlSequenceOfOperation, Privilege: manage */ \
28, /* Cluster: Thermostat, Attribute: SystemMode, Privilege: manage */ \
+ 1, /* Cluster: Thermostat User Interface Configuration, Attribute: keypad lockout, Privilege: manage */ \
}
// Parallel array data (cluster, attribute, *privilege*) for write attribute
@@ -174,6 +179,7 @@
kMatterAccessPrivilegeManage, /* Cluster: Thermostat, Attribute: MinSetpointDeadBand, Privilege: manage */ \
kMatterAccessPrivilegeManage, /* Cluster: Thermostat, Attribute: ControlSequenceOfOperation, Privilege: manage */ \
kMatterAccessPrivilegeManage, /* Cluster: Thermostat, Attribute: SystemMode, Privilege: manage */ \
+ kMatterAccessPrivilegeManage, /* Cluster: Thermostat User Interface Configuration, Attribute: keypad lockout, Privilege: manage */ \
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/zzz_generated/thermostat/zap-generated/callback-stub.cpp b/zzz_generated/thermostat/zap-generated/callback-stub.cpp
index 9e6402a..d000ee8 100644
--- a/zzz_generated/thermostat/zap-generated/callback-stub.cpp
+++ b/zzz_generated/thermostat/zap-generated/callback-stub.cpp
@@ -92,6 +92,9 @@
case ZCL_THERMOSTAT_CLUSTER_ID:
emberAfThermostatClusterInitCallback(endpoint);
break;
+ case ZCL_THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER_ID:
+ emberAfThermostatUserInterfaceConfigurationClusterInitCallback(endpoint);
+ break;
case ZCL_THREAD_NETWORK_DIAGNOSTICS_CLUSTER_ID:
emberAfThreadNetworkDiagnosticsClusterInitCallback(endpoint);
break;
@@ -218,6 +221,11 @@
// To prevent warning
(void) endpoint;
}
+void __attribute__((weak)) emberAfThermostatUserInterfaceConfigurationClusterInitCallback(EndpointId endpoint)
+{
+ // To prevent warning
+ (void) endpoint;
+}
void __attribute__((weak)) emberAfThreadNetworkDiagnosticsClusterInitCallback(EndpointId endpoint)
{
// To prevent warning
diff --git a/zzz_generated/thermostat/zap-generated/endpoint_config.h b/zzz_generated/thermostat/zap-generated/endpoint_config.h
index 6205237..083e077 100644
--- a/zzz_generated/thermostat/zap-generated/endpoint_config.h
+++ b/zzz_generated/thermostat/zap-generated/endpoint_config.h
@@ -78,7 +78,7 @@
}
// This is an array of EmberAfAttributeMinMaxValue structures.
-#define GENERATED_MIN_MAX_DEFAULT_COUNT 11
+#define GENERATED_MIN_MAX_DEFAULT_COUNT 13
#define GENERATED_MIN_MAX_DEFAULTS \
{ \
\
@@ -97,14 +97,18 @@
{ (uint16_t) 0xC80, (uint16_t) -0x6AB3, (uint16_t) 0x7FFF }, /* MaxCoolSetpointLimit */ \
{ (uint16_t) 0x19, (uint16_t) 0x0, (uint16_t) 0x19 }, /* MinSetpointDeadBand */ \
{ (uint16_t) 0x4, (uint16_t) 0x0, (uint16_t) 0x5 }, /* ControlSequenceOfOperation */ \
+ { (uint16_t) 0x1, (uint16_t) 0x0, (uint16_t) 0x7 }, /* SystemMode */ \
+ \
+ /* Endpoint: 1, Cluster: Thermostat User Interface Configuration (server) */ \
+ { (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0x1 }, /* temperature display mode */ \
{ \
- (uint16_t) 0x1, (uint16_t) 0x0, (uint16_t) 0x7 \
- } /* SystemMode */ \
+ (uint16_t) 0x0, (uint16_t) 0x0, (uint16_t) 0x5 \
+ } /* keypad lockout */ \
}
#define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask
// This is an array of EmberAfAttributeMetadata structures.
-#define GENERATED_ATTRIBUTE_COUNT 261
+#define GENERATED_ATTRIBUTE_COUNT 249
#define GENERATED_ATTRIBUTES \
{ \
\
@@ -483,50 +487,13 @@
{ 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \
{ 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(4) }, /* ClusterRevision */ \
\
- /* Endpoint: 1, Cluster: Basic (server) */ \
- { 0x00000000, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* DataModelRevision */ \
- { 0x00000001, ZAP_TYPE(CHAR_STRING), 33, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* VendorName */ \
- { 0x00000002, ZAP_TYPE(VENDOR_ID), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* VendorID */ \
- { 0x00000003, ZAP_TYPE(CHAR_STRING), 33, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* ProductName */ \
- { 0x00000004, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* ProductID */ \
- { 0x00000005, ZAP_TYPE(CHAR_STRING), 33, \
- ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(SINGLETON) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
- ZAP_EMPTY_DEFAULT() }, /* NodeLabel */ \
- { 0x00000006, ZAP_TYPE(CHAR_STRING), 3, \
- ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
- ZAP_EMPTY_DEFAULT() }, /* Location */ \
- { 0x00000007, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* HardwareVersion */ \
- { 0x00000008, ZAP_TYPE(CHAR_STRING), 65, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* HardwareVersionString */ \
- { 0x00000009, ZAP_TYPE(INT32U), 4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* SoftwareVersion */ \
- { 0x0000000A, ZAP_TYPE(CHAR_STRING), 65, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* SoftwareVersionString */ \
- { 0x0000000B, ZAP_TYPE(CHAR_STRING), 17, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* ManufacturingDate */ \
- { 0x0000000C, ZAP_TYPE(CHAR_STRING), 33, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* PartNumber */ \
- { 0x0000000D, ZAP_TYPE(LONG_CHAR_STRING), 258, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* ProductURL */ \
- { 0x0000000E, ZAP_TYPE(CHAR_STRING), 65, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* ProductLabel */ \
- { 0x0000000F, ZAP_TYPE(CHAR_STRING), 33, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* SerialNumber */ \
- { 0x00000010, ZAP_TYPE(BOOLEAN), 1, \
- ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(SINGLETON) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
- ZAP_SIMPLE_DEFAULT(0) }, /* LocalConfigDisabled */ \
- { 0x00000011, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(SINGLETON), ZAP_SIMPLE_DEFAULT(1) }, /* Reachable */ \
- { 0x00000012, ZAP_TYPE(CHAR_STRING), 33, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(SINGLETON), \
- ZAP_EMPTY_DEFAULT() }, /* UniqueID */ \
- { 0x00000013, ZAP_TYPE(STRUCT), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* CapabilityMinima */ \
+ /* Endpoint: 1, Cluster: Descriptor (server) */ \
+ { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* DeviceTypeList */ \
+ { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ServerList */ \
+ { 0x00000002, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ClientList */ \
+ { 0x00000003, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* PartsList */ \
{ 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \
- { 0x0000FFFD, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(SINGLETON), ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \
+ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* ClusterRevision */ \
\
/* Endpoint: 1, Cluster: Thermostat (server) */ \
{ 0x00000000, ZAP_TYPE(INT16S), 2, ZAP_ATTRIBUTE_MASK(NULLABLE), ZAP_EMPTY_DEFAULT() }, /* LocalTemperature */ \
@@ -534,9 +501,11 @@
{ 0x00000004, ZAP_TYPE(INT16S), 2, 0, ZAP_SIMPLE_DEFAULT(3000) }, /* AbsMaxHeatSetpointLimit */ \
{ 0x00000005, ZAP_TYPE(INT16S), 2, 0, ZAP_SIMPLE_DEFAULT(1600) }, /* AbsMinCoolSetpointLimit */ \
{ 0x00000006, ZAP_TYPE(INT16S), 2, 0, ZAP_SIMPLE_DEFAULT(3200) }, /* AbsMaxCoolSetpointLimit */ \
- { 0x00000011, ZAP_TYPE(INT16S), 2, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
+ { 0x00000011, ZAP_TYPE(INT16S), 2, \
+ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
ZAP_MIN_MAX_DEFAULTS_INDEX(2) }, /* OccupiedCoolingSetpoint */ \
- { 0x00000012, ZAP_TYPE(INT16S), 2, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
+ { 0x00000012, ZAP_TYPE(INT16S), 2, \
+ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
ZAP_MIN_MAX_DEFAULTS_INDEX(3) }, /* OccupiedHeatingSetpoint */ \
{ 0x00000015, ZAP_TYPE(INT16S), 2, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
ZAP_MIN_MAX_DEFAULTS_INDEX(4) }, /* MinHeatSetpointLimit */ \
@@ -550,10 +519,19 @@
ZAP_MIN_MAX_DEFAULTS_INDEX(8) }, /* MinSetpointDeadBand */ \
{ 0x0000001B, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
ZAP_MIN_MAX_DEFAULTS_INDEX(9) }, /* ControlSequenceOfOperation */ \
- { 0x0000001C, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
+ { 0x0000001C, ZAP_TYPE(ENUM8), 1, \
+ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(TOKENIZE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
ZAP_MIN_MAX_DEFAULTS_INDEX(10) }, /* SystemMode */ \
{ 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0x23) }, /* FeatureMap */ \
{ 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(5) }, /* ClusterRevision */ \
+ \
+ /* Endpoint: 1, Cluster: Thermostat User Interface Configuration (server) */ \
+ { 0x00000000, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
+ ZAP_MIN_MAX_DEFAULTS_INDEX(11) }, /* temperature display mode */ \
+ { 0x00000001, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE), \
+ ZAP_MIN_MAX_DEFAULTS_INDEX(12) }, /* keypad lockout */ \
+ { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \
+ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \
}
// This is an array of EmberAfCluster structures.
@@ -587,6 +565,9 @@
const EmberAfGenericClusterFunction chipFuncArrayThermostatServer[] = { \
(EmberAfGenericClusterFunction) emberAfThermostatClusterServerInitCallback, \
(EmberAfGenericClusterFunction) MatterThermostatClusterServerPreAttributeChangedCallback, \
+ }; \
+ const EmberAfGenericClusterFunction chipFuncArrayThermostatUserInterfaceConfigurationServer[] = { \
+ (EmberAfGenericClusterFunction) MatterThermostatUserInterfaceConfigurationClusterServerPreAttributeChangedCallback, \
};
// clang-format off
@@ -704,7 +685,7 @@
// clang-format on
#define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask
-#define GENERATED_CLUSTER_COUNT 29
+#define GENERATED_CLUSTER_COUNT 30
// clang-format off
#define GENERATED_CLUSTERS { \
@@ -1006,20 +987,20 @@
.generatedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 69 ) ,\
},\
{ \
- /* Endpoint: 1, Cluster: Basic (server) */ \
- .clusterId = 0x00000028, \
+ /* Endpoint: 1, Cluster: Descriptor (server) */ \
+ .clusterId = 0x0000001D, \
.attributes = ZAP_ATTRIBUTE_INDEX(223), \
- .attributeCount = 22, \
- .clusterSize = 41, \
- .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \
- .functions = chipFuncArrayBasicServer, \
+ .attributeCount = 6, \
+ .clusterSize = 4, \
+ .mask = ZAP_CLUSTER_MASK(SERVER), \
+ .functions = NULL, \
.acceptedCommandList = nullptr ,\
.generatedCommandList = nullptr ,\
},\
{ \
/* Endpoint: 1, Cluster: Thermostat (server) */ \
.clusterId = 0x00000201, \
- .attributes = ZAP_ATTRIBUTE_INDEX(245), \
+ .attributes = ZAP_ATTRIBUTE_INDEX(229), \
.attributeCount = 16, \
.clusterSize = 31, \
.mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \
@@ -1027,18 +1008,29 @@
.acceptedCommandList = ZAP_GENERATED_COMMANDS_INDEX( 76 ) ,\
.generatedCommandList = nullptr ,\
},\
+ { \
+ /* Endpoint: 1, Cluster: Thermostat User Interface Configuration (server) */ \
+ .clusterId = 0x00000204, \
+ .attributes = ZAP_ATTRIBUTE_INDEX(245), \
+ .attributeCount = 4, \
+ .clusterSize = 8, \
+ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \
+ .functions = chipFuncArrayThermostatUserInterfaceConfigurationServer, \
+ .acceptedCommandList = nullptr ,\
+ .generatedCommandList = nullptr ,\
+ },\
}
// clang-format on
#define ZAP_CLUSTER_INDEX(index) (&generatedClusters[index])
-#define ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT 27
+#define ZAP_FIXED_ENDPOINT_DATA_VERSION_COUNT 28
// This is an array of EmberAfEndpointType structures.
#define GENERATED_ENDPOINT_TYPES \
{ \
- { ZAP_CLUSTER_INDEX(0), 23, 259 }, { ZAP_CLUSTER_INDEX(23), 6, 100 }, \
+ { ZAP_CLUSTER_INDEX(0), 23, 259 }, { ZAP_CLUSTER_INDEX(23), 7, 71 }, \
}
// Largest attribute size is needed for various buffers
@@ -1047,10 +1039,10 @@
static_assert(ATTRIBUTE_LARGEST <= CHIP_CONFIG_MAX_ATTRIBUTE_STORE_ELEMENT_SIZE, "ATTRIBUTE_LARGEST larger than expected");
// Total size of singleton attributes
-#define ATTRIBUTE_SINGLETONS_SIZE (74)
+#define ATTRIBUTE_SINGLETONS_SIZE (37)
// Total size of attribute storage
-#define ATTRIBUTE_MAX_SIZE (359)
+#define ATTRIBUTE_MAX_SIZE (330)
// Number of fixed endpoints
#define FIXED_ENDPOINT_COUNT (2)
diff --git a/zzz_generated/thermostat/zap-generated/gen_config.h b/zzz_generated/thermostat/zap-generated/gen_config.h
index 0f3fd1f..86a851c 100644
--- a/zzz_generated/thermostat/zap-generated/gen_config.h
+++ b/zzz_generated/thermostat/zap-generated/gen_config.h
@@ -33,10 +33,10 @@
#define EMBER_AF_IDENTIFY_CLUSTER_SERVER_ENDPOINT_COUNT (2)
#define EMBER_AF_GROUPS_CLUSTER_SERVER_ENDPOINT_COUNT (1)
#define EMBER_AF_SCENES_CLUSTER_SERVER_ENDPOINT_COUNT (1)
-#define EMBER_AF_DESCRIPTOR_CLUSTER_SERVER_ENDPOINT_COUNT (1)
+#define EMBER_AF_DESCRIPTOR_CLUSTER_SERVER_ENDPOINT_COUNT (2)
#define EMBER_AF_BINDING_CLUSTER_SERVER_ENDPOINT_COUNT (1)
#define EMBER_AF_ACCESS_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT (1)
-#define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (2)
+#define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1)
#define EMBER_AF_OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER_CLIENT_ENDPOINT_COUNT (1)
#define EMBER_AF_OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER_SERVER_ENDPOINT_COUNT (1)
#define EMBER_AF_LOCALIZATION_CONFIGURATION_CLUSTER_SERVER_ENDPOINT_COUNT (1)
@@ -56,6 +56,7 @@
#define EMBER_AF_FIXED_LABEL_CLUSTER_SERVER_ENDPOINT_COUNT (1)
#define EMBER_AF_USER_LABEL_CLUSTER_SERVER_ENDPOINT_COUNT (1)
#define EMBER_AF_THERMOSTAT_CLUSTER_SERVER_ENDPOINT_COUNT (1)
+#define EMBER_AF_THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER_SERVER_ENDPOINT_COUNT (1)
/**** Cluster Plugins ****/
@@ -203,3 +204,8 @@
#define ZCL_USING_THERMOSTAT_CLUSTER_SERVER
#define EMBER_AF_PLUGIN_THERMOSTAT_SERVER
#define EMBER_AF_PLUGIN_THERMOSTAT
+
+// Use this macro to check if the server side of the Thermostat User Interface Configuration cluster is included
+#define ZCL_USING_THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER_SERVER
+#define EMBER_AF_PLUGIN_THERMOSTAT_USER_INTERFACE_CONFIGURATION_SERVER
+#define EMBER_AF_PLUGIN_THERMOSTAT_USER_INTERFACE_CONFIGURATION