[Telink] Add Thermostat app example (#23717)
* [Telink] Add thermostat example
* [Telink] Add new target for CI
* [Telink] Fix build after rebase
* [Telink] misspell fix
* [Telink] correct app name
diff --git a/.github/workflows/examples-telink.yaml b/.github/workflows/examples-telink.yaml
index 5f04033..d4f1a9b 100644
--- a/.github/workflows/examples-telink.yaml
+++ b/.github/workflows/examples-telink.yaml
@@ -99,6 +99,15 @@
out/telink-tlsr9518adk80d-ota-requestor/zephyr/zephyr.elf \
/tmp/bloat_reports/
+ - name: Build example Telink Thermostat App
+ run: |
+ ./scripts/run_in_build_env.sh \
+ "./scripts/build/build_examples.py --no-log-timestamps --target 'telink-tlsr9518adk80d-thermostat' build"
+ .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
+ telink tlsr9518adk80d thermostat \
+ out/telink-tlsr9518adk80d-thermostat/zephyr/zephyr.elf \
+ /tmp/bloat_reports/
+
- name: Uploading Size Reports
uses: actions/upload-artifact@v3
if: ${{ !env.ACT }}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 56b9357..f8cf998 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -434,6 +434,7 @@
"telink-tlsr9518adk80d-light",
"telink-tlsr9518adk80d-light-switch",
"telink-tlsr9518adk80d-ota-requestor",
+ "telink-tlsr9518adk80d-thermostat",
"tizen-arm-light"
]
},
diff --git a/examples/light-switch-app/telink/src/ZclCallbacks.cpp b/examples/light-switch-app/telink/src/ZclCallbacks.cpp
index 8510126..cb2b2ab 100644
--- a/examples/light-switch-app/telink/src/ZclCallbacks.cpp
+++ b/examples/light-switch-app/telink/src/ZclCallbacks.cpp
@@ -26,8 +26,8 @@
using namespace chip;
using namespace chip::app::Clusters;
-void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t mask, uint8_t type,
- uint16_t size, uint8_t * value)
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
+ uint8_t * value)
{
ClusterId clusterId = attributePath.mClusterId;
AttributeId attributeId = attributePath.mAttributeId;
diff --git a/examples/ota-requestor-app/telink/src/ZclCallbacks.cpp b/examples/ota-requestor-app/telink/src/ZclCallbacks.cpp
index 74bc8f2..159ce1f 100644
--- a/examples/ota-requestor-app/telink/src/ZclCallbacks.cpp
+++ b/examples/ota-requestor-app/telink/src/ZclCallbacks.cpp
@@ -26,8 +26,8 @@
using namespace chip;
using namespace chip::app::Clusters;
-void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t mask, uint8_t type,
- uint16_t size, uint8_t * value)
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
+ uint8_t * value)
{
ClusterId clusterId = attributePath.mClusterId;
AttributeId attributeId = attributePath.mAttributeId;
diff --git a/examples/thermostat/telink/.gitignore b/examples/thermostat/telink/.gitignore
new file mode 100644
index 0000000..84c048a
--- /dev/null
+++ b/examples/thermostat/telink/.gitignore
@@ -0,0 +1 @@
+/build/
diff --git a/examples/thermostat/telink/CMakeLists.txt b/examples/thermostat/telink/CMakeLists.txt
new file mode 100755
index 0000000..78b4f7c
--- /dev/null
+++ b/examples/thermostat/telink/CMakeLists.txt
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2022 Project CHIP Authors
+#
+# 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.
+#
+cmake_minimum_required(VERSION 3.13.1)
+
+set(BOARD tlsr9518adk80d)
+
+get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connectedhomeip REALPATH)
+get_filename_component(NLIO_ROOT ${CHIP_ROOT}/third_party/nlio/repo/include REALPATH)
+get_filename_component(TELINK_COMMON ${CHIP_ROOT}/examples/platform/telink REALPATH)
+get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH)
+
+set(CONF_FILE ${CHIP_ROOT}/config/telink/app/zephyr.conf prj.conf)
+
+# Load NCS/Zephyr build system
+list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/telink/chip-module)
+find_package(Zephyr HINTS $ENV{ZEPHYR_BASE})
+
+project(chip-telink-thermostat-example)
+
+include(${CHIP_ROOT}/config/telink/app/enable-gnu-std.cmake)
+include(${CHIP_ROOT}/src/app/chip_data_model.cmake)
+
+target_compile_options(app PRIVATE -fpermissive)
+
+target_include_directories(app PRIVATE
+ include
+ ${GEN_DIR}/app-common
+ ${GEN_DIR}/thermostat
+ ${NLIO_ROOT}
+ ${TELINK_COMMON}/util/include
+ ${TELINK_COMMON}/app/include)
+
+add_definitions(
+ "-DCHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER=<lib/address_resolve/AddressResolve_DefaultImpl.h>"
+)
+
+target_sources(app PRIVATE
+ src/AppTask.cpp
+ src/SensorManager.cpp
+ src/TemperatureManager.cpp
+ src/main.cpp
+ src/ZclCallbacks.cpp
+ ${GEN_DIR}/thermostat/zap-generated/IMClusterCommandHandler.cpp
+ ${TELINK_COMMON}/util/src/LEDWidget.cpp
+ ${TELINK_COMMON}/util/src/ButtonManager.cpp
+ ${TELINK_COMMON}/util/src/ThreadUtil.cpp)
+
+chip_configure_data_model(app
+ INCLUDE_SERVER
+ ZAP_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../thermostat-common/thermostat.zap
+)
+
+if(CONFIG_CHIP_OTA_REQUESTOR)
+ target_sources(app PRIVATE ${TELINK_COMMON}/util/src/OTAUtil.cpp)
+endif()
diff --git a/examples/thermostat/telink/Readme.md b/examples/thermostat/telink/Readme.md
new file mode 100755
index 0000000..18dd713
--- /dev/null
+++ b/examples/thermostat/telink/Readme.md
@@ -0,0 +1,157 @@
+# Matter Telink Thermostat Example Application
+
+You can use this example as a reference for creating your own application.
+
+![Telink B91 EVK](http://wiki.telink-semi.cn/wiki/assets/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/connection_chart.png)
+
+## Build and flash
+
+1. Pull docker image from repository:
+
+ ```bash
+ $ docker pull connectedhomeip/chip-build-telink:latest
+ ```
+
+1. Run docker container:
+
+ ```bash
+ $ docker run -it --rm -v ${CHIP_BASE}:/root/chip -v /dev/bus/usb:/dev/bus/usb --device-cgroup-rule "c 189:* rmw" connectedhomeip/chip-build-telink:latest
+ ```
+
+ here `${CHIP_BASE}` is directory which contains CHIP repo files **!!!Pay
+ attention that OUTPUT_DIR should contains ABSOLUTE path to output dir**
+
+1. Activate the build environment:
+
+ ```bash
+ $ source ./scripts/activate.sh
+ ```
+
+1. In the example dir run:
+
+ ```bash
+ $ west build
+ ```
+
+1. Flash binary:
+
+ ```
+ $ west flash --erase
+ ```
+
+## Usage
+
+### UART
+
+To get output from device, connect UART to following pins:
+
+| Name | Pin |
+| :--: | :---------------------------- |
+| RX | PB3 (pin 17 of J34 connector) |
+| TX | PB2 (pin 16 of J34 connector) |
+| GND | GND |
+
+### Buttons
+
+The following buttons are available on **tlsr9518adk80d** board:
+
+| Name | Function | Description |
+| :------- | :--------------------- | :----------------------------------------------------------------------------------------------------- |
+| Button 1 | Factory reset | Perform factory reset to forget currently commissioned Thread network and back to uncommissioned state |
+| Button 2 | NA | NA |
+| Button 3 | Thread start | Commission thread with static credentials and enables the Thread on device |
+| Button 4 | Open commission window | The button is opening commissioning window to perform commissioning over BLE |
+
+### LEDs
+
+**Red** LED indicates current state of Thread network. It ables to be in
+following states:
+
+| State | Description |
+| :-------------------------- | :--------------------------------------------------------------------------- |
+| Blinks with short pulses | Device is not commissioned to Thread, Thread is disabled |
+| Blinls with frequent pulses | Device is commissioned, Thread enabled. Device trying to JOIN thread network |
+| Blinks with whde pulses | Device commissioned and joined to thread network as CHILD |
+
+### CHIP tool commands
+
+1. Build
+ [chip-tool cli](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md)
+
+2. Pair with device
+
+ ```
+ ${CHIP_TOOL_DIR}/chip-tool pairing ble-thread ${NODE_ID} hex:${DATASET} ${PIN_CODE} ${DISCRIMINATOR}
+ ```
+
+ Example:
+
+ ```
+ ./chip-tool pairing ble-thread 1234 hex:0e080000000000010000000300000f35060004001fffe0020811111111222222220708fd61f77bd3df233e051000112233445566778899aabbccddeeff030e4f70656e54687265616444656d6f010212340410445f2b5ca6f2a93a55ce570a70efeecb0c0402a0fff8 20202021 3840
+ ```
+
+### OTA with Linux OTA Provider
+
+OTA feature enabled by default only for ota-requestor-app example. To enable OTA
+feature for another Telink example:
+
+- set CONFIG_CHIP_OTA_REQUESTOR=y in corresponding "prj.conf" configuration
+ file.
+
+After build application with enabled OTA feature, use next binary files:
+
+- zephyr.bin - main binary to flash PCB (Use 2MB PCB).
+- zephyr-ota.bin - binary for OTA Provider
+
+All binaries has the same SW version. To test OTA “zephyr-ota.bin” should have
+higher SW version than base SW. Set CONFIG_CHIP_DEVICE_SOFTWARE_VERSION=2 in
+corresponding “prj.conf” configuration file.
+
+Usage of OTA:
+
+- Build the [Linux OTA Provider](../../ota-provider-app/linux)
+
+ ```
+ ./scripts/examples/gn_build_example.sh examples/ota-provider-app/linux out/ota-provider-app chip_config_network_layer_ble=false
+ ```
+
+- Run the Linux OTA Provider with OTA image.
+
+ ```
+ ./chip-ota-provider-app -f zephyr-ota.bin
+ ```
+
+- Provision the Linux OTA Provider using chip-tool
+
+ ```
+ ./chip-tool pairing onnetwork ${OTA_PROVIDER_NODE_ID} 20202021
+ ```
+
+ here:
+
+ - \${OTA_PROVIDER_NODE_ID} is the node id of Linux OTA Provider
+
+- Configure the ACL of the ota-provider-app to allow access
+
+ ```
+ ./chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": null, "targets": null}]' ${OTA_PROVIDER_NODE_ID} 0
+ ```
+
+ here:
+
+ - \${OTA_PROVIDER_NODE_ID} is the node id of Linux OTA Provider
+
+- Use the chip-tool to announce the ota-provider-app to start the OTA process
+
+ ```
+ ./chip-tool otasoftwareupdaterequestor announce-ota-provider ${OTA_PROVIDER_NODE_ID} 0 0 0 ${DEVICE_NODE_ID} 0
+ ```
+
+ here:
+
+ - \${OTA_PROVIDER_NODE_ID} is the node id of Linux OTA Provider
+ - \${DEVICE_NODE_ID} is the node id of paired device
+
+Once the transfer is complete, OTA requestor sends ApplyUpdateRequest command to
+OTA provider for applying the image. Device will restart on successful
+application of OTA image.
diff --git a/examples/thermostat/telink/include/AppConfig.h b/examples/thermostat/telink/include/AppConfig.h
new file mode 100755
index 0000000..d852da9
--- /dev/null
+++ b/examples/thermostat/telink/include/AppConfig.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright (c) 2022 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
+
+// ---- Thermostat Example App Config ----
+
+// Buttons config
+#define BUTTON_PORT DEVICE_DT_GET(DT_NODELABEL(gpioc))
+
+#define BUTTON_PIN_1 2
+#define BUTTON_PIN_3 3
+#define BUTTON_PIN_4 1
+#define BUTTON_PIN_2 0
+
+// LEDs config
+// System led config
+#define SYSTEM_STATE_LED_PORT DEVICE_DT_GET(DT_NODELABEL(gpiob))
+#define SYSTEM_STATE_LED_PIN 7
diff --git a/examples/thermostat/telink/include/AppEvent.h b/examples/thermostat/telink/include/AppEvent.h
new file mode 100755
index 0000000..21933d1
--- /dev/null
+++ b/examples/thermostat/telink/include/AppEvent.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright (c) 2022 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 <cstdint>
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+ enum AppEventTypes
+ {
+ kEventType_Button = 0,
+ kEventType_Timer,
+ kEventType_Thermostat,
+ kEventType_Install,
+ };
+
+ uint16_t Type;
+
+ union
+ {
+ struct
+ {
+ uint8_t Action;
+ } ButtonEvent;
+ struct
+ {
+ void * Context;
+ } TimerEvent;
+ };
+
+ EventHandler Handler;
+};
diff --git a/examples/thermostat/telink/include/AppTask.h b/examples/thermostat/telink/include/AppTask.h
new file mode 100755
index 0000000..8a3322d
--- /dev/null
+++ b/examples/thermostat/telink/include/AppTask.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright (c) 2022 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 "AppEvent.h"
+#include "SensorManager.h"
+#include "TemperatureManager.h"
+
+#include <zephyr/drivers/gpio.h>
+
+#include <platform/CHIPDeviceLayer.h>
+
+#if CONFIG_CHIP_FACTORY_DATA
+#include <platform/telink/FactoryDataProvider.h>
+#endif
+
+#include <cstdint>
+
+struct k_timer;
+
+class AppTask
+{
+public:
+ CHIP_ERROR StartApp();
+
+ void PostEvent(AppEvent * event);
+ void UpdateClusterState();
+ void UpdateThermoStatUI();
+
+private:
+ friend AppTask & GetAppTask(void);
+ CHIP_ERROR Init();
+
+ void DispatchEvent(AppEvent * event);
+
+ static void UpdateStatusLED();
+ static void FactoryResetButtonEventHandler(void);
+ static void StartThreadButtonEventHandler(void);
+ static void StartBleAdvButtonEventHandler(void);
+
+ static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+
+ static void FactoryResetHandler(AppEvent * aEvent);
+ static void StartThreadHandler(AppEvent * aEvent);
+ static void StartBleAdvHandler(AppEvent * aEvent);
+
+ static void InitButtons(void);
+
+ static void ThreadProvisioningHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+
+ static AppTask sAppTask;
+
+#if CONFIG_CHIP_FACTORY_DATA
+ // chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::InternalFlashFactoryData> mFactoryDataProvider;
+ chip::DeviceLayer::FactoryDataProvider<chip::DeviceLayer::ExternalFlashFactoryData> mFactoryDataProvider;
+#endif
+};
+
+inline AppTask & GetAppTask(void)
+{
+ return AppTask::sAppTask;
+}
diff --git a/examples/thermostat/telink/include/CHIPProjectConfig.h b/examples/thermostat/telink/include/CHIPProjectConfig.h
new file mode 100755
index 0000000..ade0219
--- /dev/null
+++ b/examples/thermostat/telink/include/CHIPProjectConfig.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright (c) 2022 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.
+ */
+
+/**
+ * @file
+ * Example project configuration file for CHIP.
+ *
+ * This is a place to put application or project-specific overrides
+ * to the default configuration values for general CHIP features.
+ *
+ */
+
+#pragma once
+
+// Use a default pairing code if one hasn't been provisioned in flash.
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ *
+ * Enable support for Chip-over-BLE (CHIPoBLE).
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+
+/**
+ * CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE
+ *
+ * Reduce packet buffer pool size to 8 (default 15) to reduce ram consumption
+ */
+#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE 8
diff --git a/examples/thermostat/telink/include/SensorManager.h b/examples/thermostat/telink/include/SensorManager.h
new file mode 100644
index 0000000..828b3ef
--- /dev/null
+++ b/examples/thermostat/telink/include/SensorManager.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright (c) 2022 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 <stdbool.h>
+#include <stdint.h>
+
+#include "AppEvent.h"
+
+#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 TimerEventHandler(k_timer * timer);
+ static void SensorTimerEventHandler(AppEvent * aEvent);
+
+ static SensorManager sSensorManager;
+};
+
+inline SensorManager & SensorMgr()
+{
+ return SensorManager::sSensorManager;
+}
diff --git a/examples/thermostat/telink/include/TemperatureManager.h b/examples/thermostat/telink/include/TemperatureManager.h
new file mode 100644
index 0000000..c55f064
--- /dev/null
+++ b/examples/thermostat/telink/include/TemperatureManager.h
@@ -0,0 +1,67 @@
+/*
+ *
+ * Copyright (c) 2022 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 <stdbool.h>
+#include <stdint.h>
+
+#include "AppEvent.h"
+
+#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/telink/prj.conf b/examples/thermostat/telink/prj.conf
new file mode 100755
index 0000000..ad1e20d
--- /dev/null
+++ b/examples/thermostat/telink/prj.conf
@@ -0,0 +1,58 @@
+#
+# Copyright (c) 2022 Project CHIP Authors
+#
+# 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.
+#
+
+# This sample uses sample-defaults.conf to set options common for all
+# samples. This file should contain only options specific for this sample
+# or overrides of default values.
+
+# enable GPIO
+CONFIG_GPIO=y
+
+# OpenThread configs
+CONFIG_OPENTHREAD_MTD=y
+CONFIG_OPENTHREAD_FTD=n
+
+# Default OpenThread network settings
+CONFIG_OPENTHREAD_PANID=4660
+CONFIG_OPENTHREAD_CHANNEL=15
+CONFIG_OPENTHREAD_NETWORK_NAME="OpenThreadDemo"
+CONFIG_OPENTHREAD_XPANID="11:11:11:11:22:22:22:22"
+CONFIG_NET_CONFIG_IEEE802154_DEV_NAME="IEEE802154_b91"
+
+# Disable Matter OTA DFU
+CONFIG_CHIP_OTA_REQUESTOR=n
+
+# CHIP configuration
+CONFIG_CHIP_PROJECT_CONFIG="include/CHIPProjectConfig.h"
+CONFIG_CHIP_OPENTHREAD_CONFIG="../../platform/telink/project_include/OpenThreadConfig.h"
+
+CONFIG_CHIP_DEVICE_VENDOR_ID=65521
+# 32782 == 0x800E (example thermostat)
+CONFIG_CHIP_DEVICE_PRODUCT_ID=32782
+CONFIG_CHIP_DEVICE_TYPE=65535
+
+CONFIG_CHIP_DEVICE_SOFTWARE_VERSION=1
+CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING="2022"
+
+# Enable CHIP pairing automatically on application start.
+CONFIG_CHIP_ENABLE_PAIRING_AUTOSTART=y
+
+# CHIP shell
+CONFIG_CHIP_LIB_SHELL=n
+
+# Disable factory data support.
+CONFIG_CHIP_FACTORY_DATA=n
+CONFIG_CHIP_FACTORY_DATA_BUILD=n
\ No newline at end of file
diff --git a/examples/thermostat/telink/src/AppTask.cpp b/examples/thermostat/telink/src/AppTask.cpp
new file mode 100644
index 0000000..40d78ab
--- /dev/null
+++ b/examples/thermostat/telink/src/AppTask.cpp
@@ -0,0 +1,378 @@
+/*
+ *
+ * Copyright (c) 2022 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 "AppTask.h"
+
+#include "AppConfig.h"
+#include "AppEvent.h"
+#include "ButtonManager.h"
+#include "LEDWidget.h"
+
+#include "ThreadUtil.h"
+
+#include <DeviceInfoProviderImpl.h>
+#include <app-common/zap-generated/attribute-id.h>
+#include <app-common/zap-generated/attribute-type.h>
+#include <app-common/zap-generated/cluster-id.h>
+#include <app/clusters/identify-server/identify-server.h>
+#include <app/server/OnboardingCodesUtil.h>
+#include <app/server/Server.h>
+#include <credentials/DeviceAttestationCredsProvider.h>
+#include <credentials/examples/DeviceAttestationCredsExample.h>
+#include <lib/support/ErrorStr.h>
+#include <system/SystemClock.h>
+
+#if CONFIG_CHIP_OTA_REQUESTOR
+#include "OTAUtil.h"
+#endif
+
+#include <zephyr/logging/log.h>
+#include <zephyr/zephyr.h>
+
+#include <algorithm>
+
+LOG_MODULE_DECLARE(app);
+
+using namespace ::chip;
+using namespace ::chip::app;
+using namespace ::chip::Credentials;
+using namespace ::chip::DeviceLayer;
+
+namespace {
+
+constexpr int kAppEventQueueSize = 10;
+constexpr uint8_t kButtonPushEvent = 1;
+constexpr uint8_t kButtonReleaseEvent = 0;
+
+// NOTE! This key is for test/certification only and should not be available in production devices!
+// If CONFIG_CHIP_FACTORY_DATA is enabled, this value is read from the factory data.
+uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+
+K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent));
+
+LEDWidget sStatusLED;
+
+Button sFactoryResetButton;
+Button sThreadStartButton;
+Button sBleAdvStartButton;
+
+bool sIsThreadProvisioned = false;
+bool sIsThreadEnabled = false;
+bool sIsThreadAttached = false;
+bool sHaveBLEConnections = false;
+
+chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+
+void OnIdentifyTriggerEffect(Identify * identify)
+{
+ switch (identify->mCurrentEffectIdentifier)
+ {
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK:
+ ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK");
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE:
+ ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE");
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY:
+ ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY");
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE:
+ ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE");
+ break;
+ default:
+ ChipLogProgress(Zcl, "No identifier effect");
+ break;
+ }
+ return;
+}
+
+Identify sIdentify = {
+ chip::EndpointId{ 1 },
+ [](Identify *) { ChipLogProgress(Zcl, "OnIdentifyStart"); },
+ [](Identify *) { ChipLogProgress(Zcl, "OnIdentifyStop"); },
+ EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED,
+ OnIdentifyTriggerEffect,
+};
+
+} // namespace
+
+AppTask AppTask::sAppTask;
+
+CHIP_ERROR AppTask::Init()
+{
+ CHIP_ERROR err;
+
+ LOG_INF("Current Software Version: %u, %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION,
+ CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING);
+
+ // Initialize status LED
+ LEDWidget::InitGpio(SYSTEM_STATE_LED_PORT);
+ sStatusLED.Init(SYSTEM_STATE_LED_PIN);
+
+ UpdateStatusLED();
+
+ InitButtons();
+
+ // Initialize CHIP server
+#if CONFIG_CHIP_FACTORY_DATA
+ ReturnErrorOnFailure(mFactoryDataProvider.Init());
+ SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
+ SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
+ SetCommissionableDataProvider(&mFactoryDataProvider);
+ // Read EnableKey from the factory data.
+ MutableByteSpan enableKey(sTestEventTriggerEnableKey);
+ err = mFactoryDataProvider.GetEnableKey(enableKey);
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("mFactoryDataProvider.GetEnableKey() failed. Could not delegate a test event trigger");
+ memset(sTestEventTriggerEnableKey, 0, sizeof(sTestEventTriggerEnableKey));
+ }
+#else
+ SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
+
+ static CommonCaseDeviceServerInitParams initParams;
+ // static OTATestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) };
+ (void) initParams.InitializeStaticResourcesBeforeServerInit();
+ // initParams.testEventTriggerDelegate = &testEventTriggerDelegate;
+ ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams));
+
+ gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage());
+ chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
+#if CONFIG_CHIP_OTA_REQUESTOR
+ InitBasicOTARequestor();
+#endif
+
+ ConfigurationMgr().LogDeviceConfig();
+ PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
+
+ // Add CHIP event handler and start CHIP thread.
+ // Note that all the initialization code should happen prior to this point to avoid data races
+ // between the main and the CHIP threads.
+ PlatformMgr().AddEventHandler(ChipEventHandler, 0);
+
+ err = SensorMgr().Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("SensorMgr::Init() failed");
+ return err;
+ }
+ err = TempMgr().Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("TempMgr::Init() failed");
+ return err;
+ }
+
+ err = ConnectivityMgr().SetBLEDeviceName("TelinkThermo");
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("Fail to set BLE device name");
+ }
+
+ return err;
+}
+
+CHIP_ERROR AppTask::StartApp()
+{
+ CHIP_ERROR err = Init();
+
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("AppTask.Init() failed");
+ return err;
+ }
+
+ AppEvent event = {};
+
+ while (true)
+ {
+ int ret = k_msgq_get(&sAppEventQueue, &event, K_MSEC(10));
+
+ while (!ret)
+ {
+ DispatchEvent(&event);
+ ret = k_msgq_get(&sAppEventQueue, &event, K_NO_WAIT);
+ }
+
+ sStatusLED.Animate();
+ }
+}
+
+void AppTask::UpdateThermoStatUI()
+{
+ LOG_INF("Thermostat Status - M:%d T:%d'C H:%d'C C:%d'C", TempMgr().GetMode(), TempMgr().GetCurrentTemp(),
+ TempMgr().GetHeatingSetPoint(), TempMgr().GetCoolingSetPoint());
+}
+
+void AppTask::FactoryResetButtonEventHandler(void)
+{
+ AppEvent event;
+
+ event.Type = AppEvent::kEventType_Button;
+ event.ButtonEvent.Action = kButtonPushEvent;
+ event.Handler = FactoryResetHandler;
+ sAppTask.PostEvent(&event);
+}
+
+void AppTask::FactoryResetHandler(AppEvent * aEvent)
+{
+ LOG_INF("Factory Reset triggered.");
+ chip::Server::GetInstance().ScheduleFactoryReset();
+}
+
+void AppTask::StartThreadButtonEventHandler(void)
+{
+ AppEvent event;
+
+ event.Type = AppEvent::kEventType_Button;
+ event.ButtonEvent.Action = kButtonPushEvent;
+ event.Handler = StartThreadHandler;
+ sAppTask.PostEvent(&event);
+}
+
+void AppTask::StartThreadHandler(AppEvent * aEvent)
+{
+
+ if (!chip::DeviceLayer::ConnectivityMgr().IsThreadProvisioned())
+ {
+ // Switch context from BLE to Thread
+ Internal::BLEManagerImpl sInstance;
+ sInstance.SwitchToIeee802154();
+ StartDefaultThreadNetwork();
+ LOG_INF("Device is not commissioned to a Thread network. Starting with the default configuration.");
+ }
+ else
+ {
+ LOG_INF("Device is commissioned to a Thread network.");
+ }
+}
+
+void AppTask::StartBleAdvButtonEventHandler(void)
+{
+ AppEvent event;
+
+ event.Type = AppEvent::kEventType_Button;
+ event.ButtonEvent.Action = kButtonPushEvent;
+ event.Handler = StartBleAdvHandler;
+ sAppTask.PostEvent(&event);
+}
+
+void AppTask::StartBleAdvHandler(AppEvent * aEvent)
+{
+ LOG_INF("BLE advertising start button pressed");
+
+ // Don't allow on starting Matter service BLE advertising after Thread provisioning.
+ if (ConnectivityMgr().IsThreadProvisioned())
+ {
+ LOG_INF("Matter service BLE advertising not started - device is commissioned to a Thread network.");
+ return;
+ }
+
+ if (ConnectivityMgr().IsBLEAdvertisingEnabled())
+ {
+ LOG_INF("BLE advertising is already enabled");
+ return;
+ }
+
+ if (chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() != CHIP_NO_ERROR)
+ {
+ LOG_ERR("OpenBasicCommissioningWindow() failed");
+ }
+}
+
+void AppTask::UpdateStatusLED()
+{
+ if (sIsThreadProvisioned && sIsThreadEnabled)
+ {
+ if (sIsThreadAttached)
+ {
+ sStatusLED.Blink(950, 50);
+ }
+ else
+ {
+ sStatusLED.Blink(100, 100);
+ }
+ }
+ else
+ {
+ sStatusLED.Blink(50, 950);
+ }
+}
+
+void AppTask::ChipEventHandler(const ChipDeviceEvent * event, intptr_t /* arg */)
+{
+ switch (event->Type)
+ {
+ case DeviceEventType::kCHIPoBLEAdvertisingChange:
+ sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0;
+ UpdateStatusLED();
+ break;
+ case DeviceEventType::kThreadStateChange:
+ sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
+ sIsThreadEnabled = ConnectivityMgr().IsThreadEnabled();
+ sIsThreadAttached = ConnectivityMgr().IsThreadAttached();
+ UpdateStatusLED();
+ break;
+ case DeviceEventType::kThreadConnectivityChange:
+#if CONFIG_CHIP_OTA_REQUESTOR
+ if (event->ThreadConnectivityChange.Result == kConnectivity_Established)
+ {
+ InitBasicOTARequestor();
+ }
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+void AppTask::PostEvent(AppEvent * aEvent)
+{
+ if (k_msgq_put(&sAppEventQueue, aEvent, K_NO_WAIT) != 0)
+ {
+ LOG_INF("Failed to post event to app task event queue");
+ }
+}
+
+void AppTask::DispatchEvent(AppEvent * aEvent)
+{
+ if (aEvent->Handler)
+ {
+ aEvent->Handler(aEvent);
+ }
+ else
+ {
+ LOG_INF("Event received with no handler. Dropping event.");
+ }
+}
+
+void AppTask::UpdateClusterState() {}
+
+void AppTask::InitButtons(void)
+{
+ sFactoryResetButton.Configure(BUTTON_PORT, BUTTON_PIN_3, BUTTON_PIN_1, FactoryResetButtonEventHandler);
+ sThreadStartButton.Configure(BUTTON_PORT, BUTTON_PIN_3, BUTTON_PIN_2, StartThreadButtonEventHandler);
+ sBleAdvStartButton.Configure(BUTTON_PORT, BUTTON_PIN_4, BUTTON_PIN_2, StartBleAdvButtonEventHandler);
+
+ ButtonManagerInst().AddButton(sFactoryResetButton);
+ ButtonManagerInst().AddButton(sThreadStartButton);
+ ButtonManagerInst().AddButton(sBleAdvStartButton);
+}
diff --git a/examples/thermostat/telink/src/SensorManager.cpp b/examples/thermostat/telink/src/SensorManager.cpp
new file mode 100644
index 0000000..c692ae9
--- /dev/null
+++ b/examples/thermostat/telink/src/SensorManager.cpp
@@ -0,0 +1,91 @@
+/*
+ *
+ * Copyright (c) 2022 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 "SensorManager.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+#include "AppTask.h"
+
+LOG_MODULE_DECLARE(app);
+
+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 Celsius
+
+k_timer sSensorTimer;
+
+SensorManager SensorManager::sSensorManager;
+
+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 };
+
+CHIP_ERROR SensorManager::Init()
+{
+ // Initialize temp sensor timer
+ k_timer_init(&sSensorTimer, &TimerEventHandler, nullptr);
+ k_timer_user_data_set(&sSensorTimer, this);
+ k_timer_start(&sSensorTimer, K_MSEC(kSensorTimerPeriodMs), K_NO_WAIT);
+
+ return CHIP_NO_ERROR;
+}
+
+void SensorManager::TimerEventHandler(k_timer * timer)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Thermostat;
+ event.TimerEvent.Context = k_timer_user_data_get(timer);
+ event.Handler = SensorTimerEventHandler;
+ GetAppTask().PostEvent(&event);
+}
+
+void SensorManager::SensorTimerEventHandler(AppEvent * aEvent)
+{
+ int16_t temperature = 0;
+ static int16_t lastTemperature = 0;
+
+ 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;
+ }
+
+ LOG_INF("Sensor Temp is : %d", temperature);
+
+ if ((temperature >= (lastTemperature + kMinTemperatureDelta)) || temperature <= (lastTemperature - kMinTemperatureDelta))
+ {
+ lastTemperature = temperature;
+ PlatformMgr().LockChipStack();
+ app::Clusters::Thermostat::Attributes::LocalTemperature::Set(kThermostatEndpoint, temperature);
+ PlatformMgr().UnlockChipStack();
+ }
+
+ // Start next timer to handle temp sensor.
+ k_timer_start(&sSensorTimer, K_MSEC(kSensorTimerPeriodMs), K_NO_WAIT);
+}
diff --git a/examples/thermostat/telink/src/TemperatureManager.cpp b/examples/thermostat/telink/src/TemperatureManager.cpp
new file mode 100644
index 0000000..9798cc0
--- /dev/null
+++ b/examples/thermostat/telink/src/TemperatureManager.cpp
@@ -0,0 +1,139 @@
+/*
+ *
+ * Copyright (c) 2022 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 "TemperatureManager.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+#include "AppTask.h"
+#include <zephyr/logging/log.h>
+
+LOG_MODULE_DECLARE(app);
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+constexpr EndpointId kThermostatEndpoint = 1;
+
+namespace ThermAttr = chip::app::Clusters::Thermostat::Attributes;
+
+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;
+
+ 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));
+ LOG_INF("Local temp %d", Temp);
+ mCurrentTempCelsius = Temp;
+ }
+ break;
+
+ case ThermAttr::OccupiedCoolingSetpoint::Id: {
+ int8_t coolingTemp = ConvertToPrintableTemp(*((int16_t *) value));
+ LOG_INF("CoolingSetpoint %d", coolingTemp);
+ mCoolingCelsiusSetPoint = coolingTemp;
+ }
+ break;
+
+ case ThermAttr::OccupiedHeatingSetpoint::Id: {
+ int8_t heatingTemp = ConvertToPrintableTemp(*((int16_t *) value));
+ LOG_INF("HeatingSetpoint %d", heatingTemp);
+ mHeatingCelsiusSetPoint = heatingTemp;
+ }
+ break;
+
+ case ThermAttr::SystemMode::Id: {
+ LOG_INF("SystemMode %d", static_cast<uint8_t>(*value));
+ uint8_t mode = static_cast<uint8_t>(*value);
+ if (mThermMode != mode)
+ {
+ mThermMode = mode;
+ }
+ }
+ break;
+
+ default: {
+ LOG_INF("Unhandled thermostat attribute %x", attributeId);
+ return;
+ }
+ break;
+ }
+
+ 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/telink/src/ZclCallbacks.cpp b/examples/thermostat/telink/src/ZclCallbacks.cpp
new file mode 100644
index 0000000..4dc43fb
--- /dev/null
+++ b/examples/thermostat/telink/src/ZclCallbacks.cpp
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright (c) 2022 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 "AppTask.h"
+#include "TemperatureManager.h"
+
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/ConcreteAttributePath.h>
+#include <lib/support/logging/CHIPLogging.h>
+
+using namespace chip;
+using namespace chip::app::Clusters;
+
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
+ uint8_t * value)
+{
+ ClusterId clusterId = attributePath.mClusterId;
+ AttributeId attributeId = attributePath.mAttributeId;
+ ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));
+
+ if (clusterId == Identify::Id)
+ {
+ // Following print is used for printing single-byte value. Change it for printing non-single-byte values.
+ ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+ }
+ else if (clusterId == Thermostat::Id)
+ {
+ TempMgr().AttributeChangeHandler(attributePath.mEndpointId, attributeId, value, size);
+ }
+}
diff --git a/examples/thermostat/telink/src/main.cpp b/examples/thermostat/telink/src/main.cpp
new file mode 100755
index 0000000..6fdd036
--- /dev/null
+++ b/examples/thermostat/telink/src/main.cpp
@@ -0,0 +1,85 @@
+/*
+ *
+ * Copyright (c) 2022 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 "AppTask.h"
+
+#include <lib/support/CHIPMem.h>
+#include <platform/CHIPDeviceLayer.h>
+
+#include <zephyr/kernel.h>
+
+LOG_MODULE_REGISTER(app);
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+
+int main(void)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ err = chip::Platform::MemoryInit();
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("Platform::MemoryInit() failed");
+ goto exit;
+ }
+
+ LOG_INF("Init CHIP stack");
+ err = PlatformMgr().InitChipStack();
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("PlatformMgr().InitChipStack() failed");
+ goto exit;
+ }
+
+ LOG_INF("Starting CHIP task");
+ err = PlatformMgr().StartEventLoopTask();
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("PlatformMgr().StartEventLoopTask() failed");
+ goto exit;
+ }
+
+ LOG_INF("Init Thread stack");
+ err = ThreadStackMgr().InitThreadStack();
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("ThreadStackMgr().InitThreadStack() failed");
+ goto exit;
+ }
+
+#ifdef CONFIG_OPENTHREAD_MTD_SED
+ err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice);
+#elif CONFIG_OPENTHREAD_MTD
+ err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice);
+#else
+ err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router);
+#endif
+ if (err != CHIP_NO_ERROR)
+ {
+ LOG_ERR("ConnectivityMgr().SetThreadDeviceType() failed");
+ goto exit;
+ }
+
+ err = GetAppTask().StartApp();
+
+exit:
+ LOG_ERR("Exited with code %" CHIP_ERROR_FORMAT, err.Format());
+ return (err == CHIP_NO_ERROR) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/examples/thermostat/telink/third_party/connectedhomeip b/examples/thermostat/telink/third_party/connectedhomeip
new file mode 120000
index 0000000..c866b86
--- /dev/null
+++ b/examples/thermostat/telink/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../..
\ No newline at end of file
diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py
index 4c8ed88..3c424d3 100755
--- a/scripts/build/build/targets.py
+++ b/scripts/build/build/targets.py
@@ -508,6 +508,7 @@
TargetPart('light', app=TelinkApp.LIGHT),
TargetPart('light-switch', app=TelinkApp.SWITCH),
TargetPart('ota-requestor', app=TelinkApp.OTA_REQUESTOR),
+ TargetPart('thermostat', app=TelinkApp.THERMOSTAT),
])
return target
diff --git a/scripts/build/builders/telink.py b/scripts/build/builders/telink.py
index 9b448e5..a85ec7c 100644
--- a/scripts/build/builders/telink.py
+++ b/scripts/build/builders/telink.py
@@ -26,6 +26,7 @@
LIGHT = auto()
SWITCH = auto()
OTA_REQUESTOR = auto()
+ THERMOSTAT = auto()
def ExampleName(self):
if self == TelinkApp.ALL_CLUSTERS:
@@ -38,6 +39,8 @@
return 'light-switch-app'
elif self == TelinkApp.OTA_REQUESTOR:
return 'ota-requestor-app'
+ elif self == TelinkApp.THERMOSTAT:
+ return 'thermostat'
else:
raise Exception('Unknown app type: %r' % self)
@@ -52,6 +55,8 @@
return 'chip-telink-light-switch-example'
elif self == TelinkApp.OTA_REQUESTOR:
return 'chip-telink-ota-requestor-example'
+ elif self == TelinkApp.THERMOSTAT:
+ return 'chip-telink-thermostat-example'
else:
raise Exception('Unknown app type: %r' % self)
diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt
index f893b28..dcb2963 100644
--- a/scripts/build/testdata/all_targets_linux_x64.txt
+++ b/scripts/build/testdata/all_targets_linux_x64.txt
@@ -18,4 +18,4 @@
nrf-native-posix-64-tests
qpg-qpg6105-{lock,light,shell,persistent-storage}
tizen-arm-{all-clusters,all-clusters-minimal,chip-tool,light}[-no-ble][-no-wifi][-asan]
-telink-tlsr9518adk80d-{all-clusters,all-clusters-minimal,light,light-switch,ota-requestor}
+telink-tlsr9518adk80d-{all-clusters,all-clusters-minimal,light,light-switch,ota-requestor,thermostat}