diff --git a/examples/platform/silabs/DIC/matter_abs_interface/include/dic.h b/examples/platform/silabs/DIC/matter_abs_interface/include/dic.h
new file mode 100644
index 00000000000000..161af29c45017c
--- /dev/null
+++ b/examples/platform/silabs/DIC/matter_abs_interface/include/dic.h
@@ -0,0 +1,48 @@
+/**
+ * @file
+ * @brief Matter abstraction layer for Direct Internet Connectivity.
+ *******************************************************************************
+ * # License
+ * Copyright 2020 Silicon Laboratories Inc.
+ *www.silabs.com
+ *******************************************************************************
+ *
+ * The licensor of this software is Silicon
+ *Laboratories Inc. Your use of this software is
+ *governed by the terms of Silicon Labs Master
+ *Software License Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement.
+ *This software is distributed to you in Source Code
+ *format and is governed by the sections of the MSLA
+ *applicable to Source Code.
+ *
+ ******************************************************************************/
+
+#ifndef __DIC_H
+#define __DIC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "stdint.h"
+
+typedef enum {
+ DIC_OK = 0,
+ DIC_ERR_INVAL,
+ DIC_ERR_MEM,
+ DIC_ERR_FAIL,
+} dic_err_t;
+
+typedef struct {
+ uint8_t *dataP;
+ uint16_t dataLen;
+} dic_buff_t;
+
+dic_err_t DIC_Init(void);
+
+dic_err_t DIC_SendMsg(const char *subject, dic_buff_t *content);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__DIC_H
diff --git a/examples/platform/silabs/DIC/matter_abs_interface/include/dic_config.h b/examples/platform/silabs/DIC/matter_abs_interface/include/dic_config.h
new file mode 100644
index 00000000000000..3dffd44a86a57a
--- /dev/null
+++ b/examples/platform/silabs/DIC/matter_abs_interface/include/dic_config.h
@@ -0,0 +1,183 @@
+/**
+ * @file
+ * @brief Matter abstraction layer for Direct Internet Connectivity.
+ *******************************************************************************
+ * # License
+ * Copyright 2020 Silicon Laboratories Inc.
+ *www.silabs.com
+ *******************************************************************************
+ *
+ * The licensor of this software is Silicon
+ *Laboratories Inc. Your use of this software is
+ *governed by the terms of Silicon Labs Master
+ *Software License Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement.
+ *This software is distributed to you in Source Code
+ *format and is governed by the sections of the MSLA
+ *applicable to Source Code.
+ *
+ ******************************************************************************/
+
+#ifndef __DIC_CONFIG_H
+#define __DIC_CONFIG_H
+
+/*certificates*/
+#define USE_AWS 1
+#define USE_MOSQUITTO 0
+#define USE_AZURE 0
+
+/* Task Configuration*/
+#define DIC_TASK_NAME "DIC"
+#define DIC_TASK_STACK_SIZE (2*1024) //2k
+
+/* Network Configuration*/
+#define DIC_SERVER_HOST "a2m21kovu9tcsh-ats.iot.ap-southeast-1.amazonaws.com"
+#define DIC_SERVER_PORT 8883
+#define DIC_SERVER_CA_CERT ca_certificate
+#define DIC_DEVICE_CERT device_certificate
+#define DIC_DEVICE_KEY device_key
+
+#define DIC_KEEP_ALIVE 0
+
+#if USE_AWS
+
+#define DIC_CLIENT_ID "DIC_2"
+#define DIC_CLIENT_USER NULL
+#define DIC_CLIENT_PASS NULL
+
+char ca_certificate[] = "-----BEGIN CERTIFICATE-----\n"
+"MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n"
+"ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n"
+"b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n"
+"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n"
+"b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n"
+"ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n"
+"9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n"
+"IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n"
+"VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n"
+"93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n"
+"jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n"
+"AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n"
+"A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n"
+"U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n"
+"N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n"
+"o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n"
+"5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n"
+"rqXRfboQnoZsG4q5WTP468SQvvG5\n"
+"-----END CERTIFICATE-----";
+
+char device_certificate[] = "-----BEGIN CERTIFICATE-----\n"
+"MIIB/DCCAaMCFFvLxRPNwTeVQB5YtKLbEdwdcvMaMAoGCCqGSM49BAMCMIGAMQsw\n"
+"CQYDVQQGEwJJTjESMBAGA1UECAwJVGVsYW5nYW5hMQwwCgYDVQQHDANIeWQxDzAN\n"
+"BgNVBAoMBlNpbGFiczEPMA0GA1UECwwGbWF0dGVyMQ8wDQYDVQQDDAZjaGFuZHUx\n"
+"HDAaBgkqhkiG9w0BCQEWDXNoQHNpbGFicy5jb20wHhcNMjMwMzI0MTIwMzI5WhcN\n"
+"MjQwMzE4MTIwMzI5WjCBgDELMAkGA1UEBhMCSU4xEjAQBgNVBAgMCVRlbGFuZ2Fu\n"
+"YTEMMAoGA1UEBwwDSHlkMQ8wDQYDVQQKDAZTaWxhYnMxDzANBgNVBAsMBm1hdHRl\n"
+"cjEPMA0GA1UEAwwGY2hhbmR1MRwwGgYJKoZIhvcNAQkBFg1zaEBzaWxhYnMuY29t\n"
+"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWIaIixoLW8k3JFROV0Uy+ja2Awhv\n"
+"TnYXuuogAqbMsCsNB2kix3zIU6d8uYM/0QjVGBo3NT5S32BlvKa1aHaD+TAKBggq\n"
+"hkjOPQQDAgNHADBEAiAMm4+cD3en9qYFHnRpl0YmVlj2bWpJ+VSDRlkUru2JdgIg\n"
+"CLtDL0HQ9NZt+AwKGYwnBZwJLOMuBWczU4uCcXsFGUM=\n"
+"-----END CERTIFICATE-----";
+
+char device_key[] = "------BEGIN EC PRIVATE KEY-----\n"
+"MHcCAQEEIFuiGwgW2Xj8QC+SO9LXNf9v6aSb+1vqAstp2h+dUArzoAoGCCqGSM49\n"
+"AwEHoUQDQgAEWIaIixoLW8k3JFROV0Uy+ja2AwhvTnYXuuogAqbMsCsNB2kix3zI\n"
+"U6d8uYM/0QjVGBo3NT5S32BlvKa1aHaD+Q==\n"
+"-----END EC PRIVATE KEY-----";
+
+#elif USE_MOSQUITTO
+
+#define DIC_CLIENT_ID "test_client"
+#define DIC_CLIENT_USER "explorer1"
+#define DIC_CLIENT_PASS "p@ssw0rd"
+
+char ca_certificate[] = "-----BEGIN CERTIFICATE-----\n"
+"MIIDizCCAnOgAwIBAgIUHSLE8e28d9aCpdIyjFsL4hBhRuswDQYJKoZIhvcNAQEL\n"
+"BQAwVTELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAktBMQswCQYDVQQHDAJCQTELMAkG\n"
+"A1UECgwCQ0cxCzAJBgNVBAsMAklEMRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMjMw\n"
+"MjIwMTMwODEyWhcNMjgwMjIwMTMwODEyWjBVMQswCQYDVQQGEwJJTjELMAkGA1UE\n"
+"CAwCS0ExCzAJBgNVBAcMAkJBMQswCQYDVQQKDAJDRzELMAkGA1UECwwCSUQxEjAQ\n"
+"BgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
+"ALxvFGAeqIcVT4x9rcPUIdQjQn/ied6DjMDSKrl5+GFKfVwUjHF5wSh1qh55WR/S\n"
+"FVQEJ4yRzwNoRNp8YRYW6V6VUt7/gkh7Wwoct9WglFx5y0Wl7fQoQJu60gkEYS/B\n"
+"CC3W0w2mcAUgm+aboUorNMz10o1TIkhKA/Qp4YKydmbkWSYFyXg+Ab+my4Fzo/Wp\n"
+"/7/yfJJ1GDJgMBj3/BihDr5NDwJ9bW2ivCzgUCxifmsvj5dNuas6Rypgnc5LCrwR\n"
+"JpvfLo3EP/F5Sr0zSa88c154QcJDlBZYy+AWUYRbH9kPfrAyP/Xf0zpqXNcYNEpu\n"
+"k7gUSoIDDgm7gTqYcTj4IdECAwEAAaNTMFEwHQYDVR0OBBYEFKwhlzzFhGH4VUpS\n"
+"t/oobYRE1U+xMB8GA1UdIwQYMBaAFKwhlzzFhGH4VUpSt/oobYRE1U+xMA8GA1Ud\n"
+"EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBALii2W/LzxALqh6+rQWCgI+g\n"
+"FRoysTeO3s9+95PTz5ctT7WFd7+lCJ/h4W8HXA1DIhaDi/OafV+8b+CVrvLZuw/5\n"
+"PfUxCXNzqVfWWFUR8PrQc1mvGPOjqxuQdK0GuRywEezzFXbCfkS6Bg1YP0PD9Kt9\n"
+"MHHo0I1+UJ4Ce3CnVjrc5/LNqqIxOTGen3Ww2i2tcTF7AWwLpAkEoSLFjzMzQtSz\n"
+"aMjlC/3MiefJzoSa51wpNgqPjfMq7HibqbNyg+ectW/5S6FGgRAOlxSPm9hdzNWV\n"
+"l47KOeR168TSKvFa4fslvKFgsmyFUPWGi9EpBshsXsCSiiWi0yaScHSj5yq/P5E=\n"
+"-----END CERTIFICATE-----";
+
+char device_certificate[] = "-----BEGIN CERTIFICATE-----\n"
+"MIIBpzCCAU0CFAyhZKv2UJYX/5sFRapbXcMnWLZIMAoGCCqGSM49BAMCMFUxCzAJ\n"
+"BgNVBAYTAklOMQswCQYDVQQIDAJLQTELMAkGA1UEBwwCQkExCzAJBgNVBAoMAkNH\n"
+"MQswCQYDVQQLDAJDRTESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIzMDEyNTA2NDMw\n"
+"NVoXDTI0MDEyMDA2NDMwNVowVzELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAktBMQsw\n"
+"CQYDVQQHDAJCQTELMAkGA1UECgwCQ0cxCzAJBgNVBAsMAklEMRQwEgYDVQQDDAtt\n"
+"cXR0LWNsaWVudDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKOGGPfEgSpQotAE\n"
+"u8lI8hkZEPS8qiqDAyaYZnyd6Qg2LsTzpU1KFwzUgIZQPuFJNnsoP8nSDlh/9/5E\n"
+"NiqddLcwCgYIKoZIzj0EAwIDSAAwRQIhAIDQzIW+lRYPUzEHAcYDK8cuqdzFzgKN\n"
+"Ye6O46Os34GDAiBt/ODIHL3yTYd3uyBGMk0NGolFnd6L3o/Sv7OZHgsESw==\n"
+"-----END CERTIFICATE-----";
+
+char device_key[] = "-----BEGIN EC PRIVATE KEY-----\n"
+"MHcCAQEEIGdTdbc0E7+VQEjU17tPPB4jgX3sbz0oKPzoobcFtZimoAoGCCqGSM49\n"
+"AwEHoUQDQgAEo4YY98SBKlCi0AS7yUjyGRkQ9LyqKoMDJphmfJ3pCDYuxPOlTUoX\n"
+"DNSAhlA+4Uk2eyg/ydIOWH/3/kQ2Kp10tw==\n"
+"-----END EC PRIVATE KEY-----";
+
+#elif USE_AZURE
+
+#define DIC_CLIENT_ID "explorer"
+#define DIC_CLIENT_USER "SilabsAzureIOT.azure-devices.net/explorer"
+#define DIC_CLIENT_PASS NULL
+
+char ca_certificate[] = "-----BEGIN CERTIFICATE-----\n"
+"MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\n"
+"RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\n"
+"VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX\n"
+"DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y\n"
+"ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy\n"
+"VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr\n"
+"mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr\n"
+"IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK\n"
+"mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\n"
+"XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy\n"
+"dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye\n"
+"jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1\n"
+"BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3\n"
+"DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92\n"
+"9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\n"
+"jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0\n"
+"Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz\n"
+"ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\n"
+"R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n"
+"-----END CERTIFICATE-----";
+
+char device_certificate[] = "-----BEGIN CERTIFICATE-----\n"
+"MIIBpTCCAUoCFAKvmMEFCTORIRRXqRVa77vDvnU7MAoGCCqGSM49BAMCMFUxCzAJ\n"
+"BgNVBAYTAklOMQswCQYDVQQIDAJLQTELMAkGA1UEBwwCQkExCzAJBgNVBAoMAkNH\n"
+"MQswCQYDVQQLDAJDRTESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIzMDIwNzA4MDMz\n"
+"NVoXDTI0MDIwMjA4MDMzNVowVDELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAktBMQsw\n"
+"CQYDVQQHDAJCQTELMAkGA1UECgwCQ0cxCzAJBgNVBAsMAklEMREwDwYDVQQDDAhl\n"
+"eHBsb3JlcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKOGGPfEgSpQotAEu8lI\n"
+"8hkZEPS8qiqDAyaYZnyd6Qg2LsTzpU1KFwzUgIZQPuFJNnsoP8nSDlh/9/5ENiqd\n"
+"dLcwCgYIKoZIzj0EAwIDSQAwRgIhAPJy5MVJ9NYO8YvI8+fq0NTOFRYa1lZ9wz99\n"
+"oQw2HvoNAiEAp6EkfIrWy+YS5Y852YUAOE4cT+maDnueMjp12SAS+jI=\n"
+"-----END CERTIFICATE-----";
+
+char device_key[] = "-----BEGIN EC PRIVATE KEY-----\n"
+"MHcCAQEEIGdTdbc0E7+VQEjU17tPPB4jgX3sbz0oKPzoobcFtZimoAoGCCqGSM49\n"
+"AwEHoUQDQgAEo4YY98SBKlCi0AS7yUjyGRkQ9LyqKoMDJphmfJ3pCDYuxPOlTUoX\n"
+"DNSAhlA+4Uk2eyg/ydIOWH/3/kQ2Kp10tw==\n"
+"-----END EC PRIVATE KEY-----";
+
+#endif //for certificates
+
+#endif // __DIC_CONFIG_H
diff --git a/examples/platform/silabs/DIC/matter_abs_interface/src/dic.c b/examples/platform/silabs/DIC/matter_abs_interface/src/dic.c
new file mode 100644
index 00000000000000..177875bdebbaab
--- /dev/null
+++ b/examples/platform/silabs/DIC/matter_abs_interface/src/dic.c
@@ -0,0 +1,209 @@
+/**
+ * @file
+ * @brief Matter abstraction layer for Direct Internet Connectivity.
+ *******************************************************************************
+ * # License
+ * Copyright 2020 Silicon Laboratories Inc.
+ *www.silabs.com
+ *******************************************************************************
+ *
+ * The licensor of this software is Silicon
+ *Laboratories Inc. Your use of this software is
+ *governed by the terms of Silicon Labs Master
+ *Software License Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement.
+ *This software is distributed to you in Source Code
+ *format and is governed by the sections of the MSLA
+ *applicable to Source Code.
+ *
+ ******************************************************************************/
+
+#include "dic.h"
+#include "dic_config.h"
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+#include "MQTT_transport.h"
+#include "mqtt.h"
+#ifdef SIWX_917
+#include "siwx917_utils.h"
+#else
+#include "efr32_utils.h"
+#endif
+
+#include //for bool
+#include // for memset
+
+#define DIC_TOPIC_PREFIX "silabs/matter/"
+
+static TaskHandle_t dicTask;
+static mqtt_client_t *mqtt_client;
+static EventGroupHandle_t dicEvents = NULL;
+static MQTT_Transport_t *transport = NULL;
+static mqtt_transport_intf_t trans;
+static bool end_loop;
+static bool init_complete;
+
+static void dic_mqtt_conn_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
+{
+ (void)client;
+ (void)arg;
+
+ SILABS_LOG("DIC: mqtt connection status: %u", status);
+ if (status != MQTT_CONNECT_ACCEPTED)
+ {
+ if (dicTask) end_loop = true;
+ }
+}
+
+void dic_tcp_connect_cb(err_t err){
+ SILABS_LOG("connection callback new");
+ if(err == ERR_OK){
+ struct mqtt_connect_client_info_t connect_info;
+ mqtt_err_t mret;
+ /* Connect to MQTT broker/cloud */
+ memset(&connect_info,0,sizeof(connect_info));
+ connect_info.client_id = DIC_CLIENT_ID;
+ connect_info.keep_alive = DIC_KEEP_ALIVE;
+ connect_info.client_user = DIC_CLIENT_USER;
+ connect_info.client_pass = DIC_CLIENT_PASS;
+
+ if ((mret = mqtt_client_connect(mqtt_client,(void*)&trans,dic_mqtt_conn_cb,NULL,&connect_info)) != ERR_OK){
+ SILABS_LOG("MQTT Connection failed %d",mret);
+ init_complete = false;
+ goto DIC_error;
+ }
+ init_complete = true;
+ return;
+ }
+ init_complete = false;
+DIC_error:
+ vTaskDelete(dicTask);
+ dicTask = NULL;
+ return;
+}
+
+static void dic_task_fn(void *args)
+{
+ /* get MQTT client handle */
+ err_t ret;
+
+ vTaskDelay(10000);
+
+ mqtt_client = mqtt_client_new();
+ if (!mqtt_client)
+ {
+ SILABS_LOG("Failed to create mqtt client");
+ goto DIC_error;
+ }
+
+ memset(&trans, 0x00, sizeof(mqtt_transport_intf_t));
+
+ /* Get transport handle*/
+ transport = MQTT_Transport_Init(&trans,mqtt_client,dicEvents);
+ if (!transport)
+ {
+ SILABS_LOG("Failed to create mqtt transport");
+ goto DIC_error;
+ }
+
+ /* set SSL configuration for TLS transport connection*/
+ if (0 != MQTT_Transport_SSLConfigure(transport, (uint8_t *)DIC_SERVER_CA_CERT, strlen(DIC_SERVER_CA_CERT)+1,
+ (uint8_t *)DIC_DEVICE_KEY, strlen(DIC_DEVICE_KEY)+1, NULL, 0, \
+ (uint8_t *)DIC_DEVICE_CERT, strlen(DIC_DEVICE_CERT)+1))
+ {
+ SILABS_LOG("Failed to configure SSL to mqtt transport");
+ goto DIC_error;
+ }
+
+ /* establish transport connection with remote */
+
+ if ((ret = MQTT_Transport_Connect(transport, DIC_SERVER_HOST, DIC_SERVER_PORT, dic_tcp_connect_cb)) != ERR_OK){
+ SILABS_LOG("Transport Connection failed %d",ret);
+ goto DIC_error;
+ }
+
+ (void)args;
+ while (!end_loop)
+ {
+ EventBits_t event;
+ event = xEventGroupWaitBits(dicEvents, SIGNAL_TRANSINTF_RX | SIGNAL_TRANSINTF_TX_ACK | SIGNAL_TRANSINTF_CONN_CLOSE | SIGNAL_TRANSINTF_MBEDTLS_RX, 1, 0, portMAX_DELAY);
+ if (event & SIGNAL_TRANSINTF_CONN_CLOSE)
+ {
+ //mqtt_close(client, MQTT_CONNECT_DISCONNECTED);
+ mqtt_close(mqtt_client, MQTT_CONNECT_DISCONNECTED);
+ end_loop = true;
+ }
+ else
+ {
+ if (event & SIGNAL_TRANSINTF_RX)
+ mqtt_process(mqtt_client, 0);
+ else if (event & 2)
+ mqtt_process(mqtt_client, SIGNAL_TRANSINTF_TX_ACK);
+ if (event & SIGNAL_TRANSINTF_MBEDTLS_RX)
+ transport_process_mbedtls_rx(transport);
+ }
+ }
+ init_complete = false;
+ dicTask = NULL;
+ vTaskDelete(NULL);
+
+DIC_error:
+ vTaskDelete(dicTask);
+ dicTask = NULL;
+ return;
+}
+
+void dic_pub_resp_cb(void *arg, mqtt_err_t err)
+{
+ (void)arg;
+ SILABS_LOG("dic publish data %s", err != MQTT_ERR_OK ? "failed!" : "successful!");
+}
+
+dic_err_t DIC_Init()
+{
+ if (dicTask)
+ {
+ SILABS_LOG("DIC already initialized, dic task is running");
+ return DIC_OK;
+ }
+ /* Create events group used to receive events from transport layer*/
+ dicEvents = xEventGroupCreate();
+ if (!dicEvents)
+ {
+ SILABS_LOG("Failed to create DIC event groups");
+ goto DIC_error;
+ }
+ if ((pdPASS != xTaskCreate(dic_task_fn, DIC_TASK_NAME, DIC_TASK_STACK_SIZE, NULL, 1, &dicTask))
+ || !dicTask)
+ {
+ SILABS_LOG("Failed to create DIC Task");
+ return DIC_ERR_MEM;
+ }
+ /* TODO: Register data and pub callback and subscribe if cloud to app messages are expected*/
+ return DIC_OK;
+DIC_error:
+vTaskDelete(dicTask);
+ dicTask = NULL;
+ return DIC_ERR_FAIL;
+}
+
+dic_err_t DIC_SendMsg(const char * subject, dic_buff_t *content)
+{
+ if (!subject || !content || !content->dataP)
+ {
+ SILABS_LOG("null args passed to DIC_SendMsg()");
+ return DIC_ERR_INVAL;
+ }
+ if(!init_complete)
+ {
+ SILABS_LOG("Err: DIC not in valid state!");
+ return DIC_ERR_FAIL;
+ }
+ if (MQTT_ERR_OK != mqtt_publish(mqtt_client, subject, content->dataP, content->dataLen, 0, 0, dic_pub_resp_cb, NULL))
+ {
+ SILABS_LOG("Err: failed request publish!");
+ return DIC_ERR_FAIL;
+ }
+ return DIC_OK;
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/.gn b/silabs_examples/Direct_Internet_lighting-app/SiWx917/.gn
new file mode 100644
index 00000000000000..3d48789e30ab3d
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2020 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.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+
+ import("//args.gni")
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/BUILD.gn b/silabs_examples/Direct_Internet_lighting-app/SiWx917/BUILD.gn
new file mode 100644
index 00000000000000..641dc5b6182ec1
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/BUILD.gn
@@ -0,0 +1,165 @@
+# Copyright (c) 2020 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.
+
+import("//build_overrides/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${build_root}/config/defaults.gni")
+import("${chip_root}/third_party/silabs/SiWx917_sdk.gni")
+import("${efr32_sdk_build_root}/silabs_executable.gni")
+
+import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni")
+import("${chip_root}/src/platform/device.gni")
+
+if (chip_enable_pw_rpc) {
+ import("//build_overrides/pigweed.gni")
+ import("$dir_pw_build/target_types.gni")
+}
+
+assert(current_os == "freertos")
+
+efr32_project_dir = "${chip_root}/silabs_examples/Direct_Internet_lighting-app/SiWx917"
+examples_plat_dir = "${chip_root}/examples/platform/silabs/SiWx917"
+examples_common_plat_dir = "${chip_root}/examples/platform/silabs"
+
+import("${examples_plat_dir}/args.gni")
+declare_args() {
+ # Dump memory usage at link time.
+ chip_print_memory_usage = false
+}
+
+siwx917_sdk("sdk") {
+ sources = [
+ "${efr32_project_dir}/include/CHIPProjectConfig.h",
+ "${examples_plat_dir}/FreeRTOSConfig.h",
+ ]
+
+ include_dirs = [
+ "${chip_root}/src/platform/silabs/SiWx917",
+ "${efr32_project_dir}/include",
+ "${examples_plat_dir}",
+ "${chip_root}/src/lib",
+ "${examples_common_plat_dir}",
+ ]
+
+ defines = []
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "HAL_VCOM_ENABLE=1",
+ "PW_RPC_ENABLED",
+ ]
+ }
+}
+
+silabs_executable("Direct_Internet_lighting_app") {
+ output_name = "chip-siwx917-Direct_Internet_lighting-example.out"
+ include_dirs = [ "include" ]
+ defines = []
+
+ sources = [
+ "src/AppTask.cpp",
+ "src/LightingManager.cpp",
+ "src/ZclCallbacks.cpp",
+ "src/main.cpp",
+ ]
+
+ deps = [
+ ":sdk",
+ "${examples_plat_dir}:siwx917-common",
+ app_data_model,
+ ]
+
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "PW_RPC_ENABLED",
+ "PW_RPC_ATTRIBUTE_SERVICE=1",
+ "PW_RPC_BUTTON_SERVICE=1",
+ "PW_RPC_DESCRIPTOR_SERVICE=1",
+ "PW_RPC_DEVICE_SERVICE=1",
+ "PW_RPC_LIGHTING_SERVICE=1",
+ "PW_RPC_OTCLI_SERVICE=1",
+ "PW_RPC_THREAD_SERVICE=1",
+ "PW_RPC_TRACING_SERVICE=1",
+ ]
+
+ sources += [
+ "${chip_root}/examples/common/pigweed/RpcService.cpp",
+ "${chip_root}/examples/common/pigweed/efr32/PigweedLoggerMutex.cpp",
+ "${examples_common_plat_dir}/PigweedLogger.cpp",
+ "${examples_common_plat_dir}/Rpc.cpp",
+ ]
+
+ deps += [
+ "$dir_pw_hdlc:rpc_channel_output",
+ "$dir_pw_stream:sys_io_stream",
+ "$dir_pw_trace",
+ "$dir_pw_trace_tokenized",
+ "$dir_pw_trace_tokenized:trace_rpc_service",
+ "${chip_root}/config/efr32/lib/pw_rpc:pw_rpc",
+ "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:Direct_Internet_lighting_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:ot_cli_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:thread_service.nanopb_rpc",
+ "${examples_plat_dir}/pw_sys_io:pw_sys_io_siwx917",
+ ]
+
+ deps += pw_build_LINK_DEPS
+
+ include_dirs += [
+ "${chip_root}/examples/common",
+ "${chip_root}/examples/common/pigweed/efr32",
+ ]
+ }
+
+ ldscript = "${examples_plat_dir}/ldscripts/${silabs_family}.ld"
+
+ inputs = [ ldscript ]
+
+ ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ]
+
+ if (chip_print_memory_usage) {
+ ldflags += [
+ "-Wl,--print-memory-usage",
+ "-fstack-usage",
+ ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ ldflags += [
+ "-Wl,--defsym",
+ "-Wl,SILABS_WIFI=1",
+ ]
+ }
+
+ # MQTT
+ if (enable_dic) {
+ deps += [ "${examples_plat_dir}:efr32-dic" ]
+ }
+
+ output_dir = root_out_dir
+}
+
+group("siwx917") {
+ deps = [ ":Direct_Internet_lighting_app" ]
+}
+
+group("default") {
+ deps = [ ":siwx917" ]
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/README.md b/silabs_examples/Direct_Internet_lighting-app/SiWx917/README.md
new file mode 100644
index 00000000000000..46e1b6c0fd6d79
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/README.md
@@ -0,0 +1,234 @@
+# Matter SiWx917 Lighting Example
+
+An example showing the use of CHIP on the Silicon Labs SiWx917.
+
+
+
+- [Matter SiWx917 Lighting Example](#matter-siwx917-lighting-example)
+ - [Introduction](#introduction)
+ - [Building](#building)
+ - [Flashing the Application](#flashing-the-application)
+ - [Viewing Logging Output](#viewing-logging-output)
+ - [Running the Complete Example](#running-the-complete-example)
+ - [Notes](#notes)
+ - [Memory settings](#memory-settings)
+ - [Group Communication (Multicast)](#group-communication-multicast)
+ - [Building options](#building-options)
+ - [Disabling logging](#disabling-logging)
+ - [Debug build / release build](#debug-build--release-build)
+ - [Disabling LCD](#disabling-lcd)
+ - [KVS maximum entry count](#kvs-maximum-entry-count)
+
+
+
+> **NOTE:** Silicon Laboratories now maintains a public matter GitHub repo with
+> frequent releases thoroughly tested and validated. Developers looking to
+> develop matter products with silabs hardware are encouraged to use our latest
+> release with added tools and documentation.
+> [Silabs Matter Github](https://github.com/SiliconLabs/matter/releases)
+
+
+
+## Introduction
+
+The SiWx917 lighting example provides a baseline demonstration of a Light
+control device, built using Matter, the Silicon Labs Gecko SDK, and the Silicon
+Labs WiseMCU SDK. It can be controlled by a Chip controller over a Wi-Fi
+network.
+
+The SiWx917 device can be commissioned over Bluetooth Low Energy where the
+device and the Chip controller will exchange security information with the
+rendezvous procedure. Wi-Fi Network credentials are then provided to the SiWx917
+device which will then join the Wi-Fi network.
+
+If the LCD is enabled, the LCD on the Silabs WSTK shows a QR Code containing the
+needed commissioning information for the BLE connection and starting the
+rendezvous procedure.
+
+The lighting example is intended to serve both as a means to explore the
+workings of Matter as well as a template for creating real products based on the
+Silicon Labs platform.
+
+
+
+## Building
+
+- Download the
+ [Simplicity Commander](https://www.silabs.com/mcu/programming-options)
+ command line tool, and ensure that `commander` is in your shell search path.
+ (For Mac OS X, `commander` is located inside
+ `Commander.app/Contents/MacOS/`.)
+
+- Download and install a suitable ARM GCC tool chain:
+ [GNU Arm Embedded Toolchain (arm-none-eabi)](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads)
+
+- Install some additional tools (likely already present for CHIP developers):
+
+ - Linux: `sudo apt-get install git ninja-build`
+
+ - Mac OS X: `brew install ninja`
+
+- Supported hardware:
+
+ - > For the latest supported hardware please refer to the
+ > [Hardware Requirements](https://github.com/SiliconLabs/matter/blob/latest/docs/silabs/general/HARDWARE_REQUIREMENTS.md)
+ > in the Silicon Labs Matter Github Repo
+
+* Build the example application:
+
+ cd ~/connectedhomeip
+ ./scripts/examples/gn_efr32_example.sh silabs_examples/Direct_Internet_lighting-app/SiWx917/ out/lighting-app BRD4325B
+
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/matter
+ $ rm -rf ./out/
+
+ OR use GN/Ninja directly
+
+ $ cd ~/matter/examples/lighting-app/efr32
+ $ git submodule update --init
+ $ source third_party/matter/scripts/activate.sh
+ $ export EFR32_BOARD=BRD4161A
+ $ gn gen out/debug
+ $ ninja -C out/debug
+
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/matter/examples/lighting-app/efr32
+ $ rm -rf out/
+
+* Build the example as Sleepy End Device (SED)
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32/ ./out/lighting-app_SED BRD4161A --sed
+
+ or use gn as previously mentioned but adding the following arguments:
+
+ $ gn gen out/debug '--args=silabs_board="BRD4161A" enable_sleepy_device=true chip_openthread_ftd=false'
+
+* Build the example with pigweed RPC
+
+ $ ./scripts/examples/gn_efr32_example.sh silabs_examples/Direct_Internet_lighting-app/efr32/ out/lighting_app_rpc BRD4161A 'import("//with_pw_rpc.gni")'
+
+ or use GN/Ninja Directly
+
+ $ cd ~/matter/examples/lighting-app/efr32
+ $ git submodule update --init
+ $ source third_party/matter/scripts/activate.sh
+ $ export EFR32_BOARD=BRD4161A
+ $ gn gen out/debug --args='import("//with_pw_rpc.gni")'
+ $ ninja -C out/debug
+
+ [Running Pigweed RPC console](#running-pigweed-rpc-console)
+
+For more build options, help is provided when running the build script without
+arguments
+
+ ./scripts/examples/gn_efr32_example.sh
+
+
+
+## Flashing the Application
+
+- On the command line:
+
+ $ cd ~/matter/examples/lighting-app/efr32
+ $ python3 out/debug/chip-efr32-lighting-example.flash.py
+
+- Or with the Ozone debugger, just load the .out file.
+
+
+
+## Viewing Logging Output
+
+The example application's logging output can be viewed in the Ozone Debugger.
+
+
+
+## Running the Complete Example
+
+- You can provision and control the Chip device using the chip-tool standalone
+
+ [chip-tool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md)
+
+ Here is an example with the chip-tool:
+
+ - > $SSID and $PSK are the SSID and passcode of your Wi-Fi Access Point.
+
+ ```
+ chip-tool pairing ble-wifi 1122 $SSID $PSK 20202021 3840
+
+ chip-tool onoff on 1 1
+ ```
+
+### Notes
+
+- Depending on your network settings your router might not provide native IPv6
+ addresses to your devices (Router / PC). If this is the case, you need to
+ add a static IPv6 addresses on both devices and then an IPv6 route to your
+ router on your PC
+
+ - On PC(Linux): `sudo ip addr add dev 2002::1/64`
+
+ - Add IPv6 route on PC(Linux)
+ `sudo ip route add /64 via 2002::2`
+
+## Memory settings
+
+While most of the RAM usage in CHIP is static, allowing easier debugging and
+optimization with symbols analysis, we still need some HEAP for the crypto and
+Wi-Fi stack. Size of the HEAP can be modified by changing the value of the
+`configTOTAL_HEAP_SIZE` define inside of the FreeRTOSConfig.h file of this
+example. Please take note that a HEAP size smaller than 13k can and will cause a
+Mbedtls failure during the BLE rendez-vous or CASE session
+
+To track memory usage you can set `enable_heap_monitoring = true` either in the
+BUILD.gn file or pass it as a build argument to gn. This will print on the RTT
+console the RAM usage of each individual task and the number of Memory
+allocation and Free. While this is not extensive monitoring you're welcome to
+modify `examples/platform/silabs/SiWx917/MemMonitoring.cpp` to add your own
+memory tracking code inside the `trackAlloc` and `trackFree` function
+
+## Group Communication (Multicast)
+
+With this lighting example you can also use group communication to send Lighting
+commands to multiples devices at once. Please refer to the
+[chip-tool documentation](../../../chip-tool/README.md) _Configuring the server
+side for Group Commands_ and _Using the Client to Send Group (Multicast) Matter
+Commands_
+
+## Building options
+
+All of Silabs's examples within the Matter repo have all the features enabled by
+default, as to provide the best end user experience. However some of those
+features can easily be toggled on or off. Here is a short list of options to be
+passed to the build scripts.
+
+### Disabling logging
+
+`chip_progress_logging, chip_detail_logging, chip_automation_logging`
+
+ $ ./scripts/examples/gn_efr32_example.sh ./silabs_examples/Direct_Internet_lighting-app/SiWx917 ./out/lighting-app BRD4325B "chip_detail_logging=false chip_automation_logging=false chip_progress_logging=false"
+
+### Debug build / release build
+
+`is_debug`
+
+ $ ./scripts/examples/gn_efr32_example.sh ./silabs_examples/Direct_Internet_lighting-app/SiWx917 ./out/lighting-app BRD4325B "is_debug=false"
+
+### Disabling LCD
+
+`show_qr_code`
+
+ $ ./scripts/examples/gn_efr32_example.sh ./silabs_examples/Direct_Internet_lighting-app/
+ /SiWx917 ./out/lighting-app BRD4325B "show_qr_code=false"
+
+### KVS maximum entry count
+
+`kvs_max_entries`
+
+ Set the maximum Kvs entries that can be stored in NVM (Default 75)
+ Thresholds: 30 <= kvs_max_entries <= 255
+
+ $ ./scripts/examples/gn_efr32_example.sh ./silabs_examples/Direct_Internet_lighting-app/
+ /SiWx917 ./out/lighting-app BRD4325B kvs_max_entries=50
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/args.gni b/silabs_examples/Direct_Internet_lighting-app/SiWx917/args.gni
new file mode 100644
index 00000000000000..ef1b4fbbe507a6
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/args.gni
@@ -0,0 +1,21 @@
+# Copyright (c) 2020 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.
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+
+siwx917_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+import("${chip_root}/src/platform/silabs/SiWx917/args.gni")
+
+app_data_model = "${chip_root}/silabs_examples/Direct_Internet_lighting-app/data_model:silabs-lighting"
+chip_enable_ota_requestor = true
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/build_overrides b/silabs_examples/Direct_Internet_lighting-app/SiWx917/build_overrides
new file mode 120000
index 00000000000000..f2758328a72777
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/build_overrides
@@ -0,0 +1 @@
+../../../examples/build_overrides
\ No newline at end of file
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/AppConfig.h b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/AppConfig.h
new file mode 100644
index 00000000000000..b86af8b22c2213
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/AppConfig.h
@@ -0,0 +1,30 @@
+/*
+ *
+ * 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 "siwx917_utils.h"
+
+// ---- Lighting Example App Config ----
+
+#define APP_TASK_NAME "Lit"
+
+// Time it takes in ms for the simulated actuator to move from one
+// state to another.
+#define ACTUATOR_MOVEMENT_PERIOS_MS 10
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/AppEvent.h b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/AppEvent.h
new file mode 100644
index 00000000000000..7a19b719edad25
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/AppEvent.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2018 Nest Labs, Inc.
+ * 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
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+ enum AppEventTypes
+ {
+ kEventType_Button = 0,
+ kEventType_Timer,
+ kEventType_Light,
+ kEventType_Install,
+ };
+
+ uint16_t Type;
+
+ union
+ {
+ struct
+ {
+ uint8_t Action;
+ } ButtonEvent;
+ struct
+ {
+ void * Context;
+ } TimerEvent;
+ struct
+ {
+ uint8_t Action;
+ int32_t Actor;
+ } LightEvent;
+ };
+
+ EventHandler Handler;
+};
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/AppTask.h b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/AppTask.h
new file mode 100644
index 00000000000000..0310e9e187c80c
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/AppTask.h
@@ -0,0 +1,134 @@
+/*
+ *
+ * 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
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include
+#include
+
+#include "AppEvent.h"
+#include "BaseApplication.h"
+#include "FreeRTOS.h"
+#include "LightingManager.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include
+#include
+#include
+#include
+
+/**********************************************************
+ * Defines
+ *********************************************************/
+// Button specific defines for SiWx917
+#define SL_SIMPLE_BUTTON_PRESSED 1
+#define SIWx917_BTN0 0
+#define SIWx917_BTN1 1
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+
+/**********************************************************
+ * AppTask Declaration
+ *********************************************************/
+
+class AppTask : public BaseApplication
+{
+
+public:
+ AppTask() = default;
+
+ static AppTask & GetAppTask() { return sAppTask; }
+
+ /**
+ * @brief AppTask task main loop function
+ *
+ * @param pvParameter FreeRTOS task parameter
+ */
+ static void AppTaskMain(void * pvParameter);
+
+ CHIP_ERROR StartAppTask();
+
+ /**
+ * @brief Event handler when a button is pressed
+ * Function posts an event for button processing
+ *
+ * @param button - btn0 or btn1
+ * @param btnAction button action - SL_SIMPLE_BUTTON_PRESSED,
+ * SL_SIMPLE_BUTTON_RELEASED or SL_SIMPLE_BUTTON_DISABLED
+ */
+ void ButtonEventHandler(uint8_t button, uint8_t btnAction);
+
+ /**
+ * @brief Callback called by the identify-server when an identify command is received
+ *
+ * @param identify identify structure the command applies on
+ */
+ static void OnIdentifyStart(Identify * identify);
+
+ /**
+ * @brief Callback called by the identify-server when an identify command is stopped or finished
+ *
+ * @param identify identify structure the command applies on
+ */
+ static void OnIdentifyStop(Identify * identify);
+
+ void PostLightActionRequest(int32_t aActor, LightingManager::Action_t aAction);
+
+private:
+ static AppTask sAppTask;
+
+ static void ActionInitiated(LightingManager::Action_t aAction, int32_t aActor);
+ static void ActionCompleted(LightingManager::Action_t aAction);
+ static void LightActionEventHandler(AppEvent * aEvent);
+
+ static void UpdateClusterState(intptr_t context);
+
+ /**
+ * @brief AppTask initialisation function
+ *
+ * @return CHIP_ERROR
+ */
+ CHIP_ERROR Init();
+
+ /**
+ * @brief PB0 Button event processing function
+ * Press and hold will trigger a factory reset timer start
+ * Press and release will restart BLEAdvertising if not commisionned
+ *
+ * @param aEvent button event being processed
+ */
+ static void ButtonHandler(AppEvent * aEvent);
+
+ /**
+ * @brief PB1 Button event processing function
+ * Function triggers a switch action sent to the CHIP task
+ *
+ * @param aEvent button event being processed
+ */
+ static void SwitchActionEventHandler(AppEvent * aEvent);
+};
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/CHIPProjectConfig.h b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/CHIPProjectConfig.h
new file mode 100644
index 00000000000000..00df921596102a
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/CHIPProjectConfig.h
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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.
+ */
+
+/**
+ * @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.
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+#endif
+
+// For convenience, Chip Security Test Mode can be enabled and the
+// requirement for authentication in various protocols can be disabled.
+//
+// WARNING: These options make it possible to circumvent basic Chip security functionality,
+// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
+//
+#define CHIP_CONFIG_SECURITY_TEST_MODE 0
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ * 0x8005: example lighting app
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ *
+ * Enable support for Chip-over-BLE (CHIPoBLE).
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+
+/**
+ * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
+ *
+ * Enables the use of a hard-coded default serial number if none
+ * is found in Chip NV storage.
+ */
+#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
+ *
+ * Enable recording UTC timestamps.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE
+ *
+ * A size, in bytes, of the individual debug event logging buffer.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512)
+
+/**
+ * @def CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL
+ *
+ * @brief
+ * Active retransmit interval, or time to wait before retransmission after
+ * subsequent failures in milliseconds.
+ *
+ * This is the default value, that might be adjusted by end device depending on its
+ * needs (e.g. sleeping period) using Service Discovery TXT record CRA key.
+ *
+ */
+#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32)
+
+#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/DeviceConfig.h b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/DeviceConfig.h
new file mode 100644
index 00000000000000..18af7b2c9c8415
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/DeviceConfig.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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
+
+#ifdef SIWX917_USE_COMISSIONABLE_DATA
+
+uint32_t discriminatorValue = 3840;
+uint64_t passcode = 20202021;
+uint32_t spake2Interation = 1000;
+char spake2Salt[] = "U1BBS0UyUCBLZXkgU2FsdA==";
+char spake2Verifier[] = "uWFwqugDNGiEck/po7KHwwMwwqZgN10XuyBajPGuyzUEV/iree4lOrao5GuwnlQ65CJzbeUB49s31EH+NEkg0JVI5MGCQGMMT/"
+ "SRPFNRODm3wH/MBiehuFc6FJ/NH6Rmzw==";
+char genSpake2Path[] = "";
+uint32_t productId = 32773;
+uint32_t vendorId = 65521;
+char productName[] = "";
+char vendorName[] = "";
+char hwVersionString[] = "";
+uint32_t rotatingId;
+uint32_t commissionableFlow = 1;
+uint8_t rendezvousFlag = 2;
+
+#endif
\ No newline at end of file
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/LightingManager.h b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/LightingManager.h
new file mode 100644
index 00000000000000..6d286faa30ef96
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/include/LightingManager.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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
+#include
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include
+
+#include
+
+class LightingManager
+{
+public:
+ enum Action_t
+ {
+ ON_ACTION = 0,
+ OFF_ACTION,
+
+ INVALID_ACTION
+ } Action;
+
+ enum State_t
+ {
+ kState_OffInitiated = 0,
+ kState_OffCompleted,
+ kState_OnInitiated,
+ kState_OnCompleted,
+ } State;
+
+ CHIP_ERROR Init();
+ bool IsLightOn();
+ void EnableAutoTurnOff(bool aOn);
+ void SetAutoTurnOffDuration(uint32_t aDurationInSecs);
+ bool IsActionInProgress();
+ bool InitiateAction(int32_t aActor, Action_t aAction);
+
+ typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor);
+ typedef void (*Callback_fn_completed)(Action_t);
+ void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB);
+
+ static void OnTriggerOffWithEffect(OnOffEffect * effect);
+
+private:
+ friend LightingManager & LightMgr(void);
+ State_t mState;
+
+ Callback_fn_initiated mActionInitiated_CB;
+ Callback_fn_completed mActionCompleted_CB;
+
+ bool mAutoTurnOff;
+ uint32_t mAutoTurnOffDuration;
+ bool mAutoTurnOffTimerArmed;
+ bool mOffEffectArmed;
+
+ void CancelTimer(void);
+ void StartTimer(uint32_t aTimeoutMs);
+
+ static void TimerEventHandler(TimerHandle_t xTimer);
+ static void AutoTurnOffTimerEventHandler(AppEvent * aEvent);
+ static void ActuatorMovementTimerEventHandler(AppEvent * aEvent);
+ static void OffEffectTimerEventHandler(AppEvent * aEvent);
+
+ static LightingManager sLight;
+};
+
+inline LightingManager & LightMgr(void)
+{
+ return LightingManager::sLight;
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/AppTask.cpp b/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/AppTask.cpp
new file mode 100644
index 00000000000000..4de5eab25a3265
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/AppTask.cpp
@@ -0,0 +1,336 @@
+/*
+ *
+ * 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 "AppTask.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+
+#include
+
+#ifdef DIC_ENABLE
+#include "dic.h"
+#endif
+
+#ifdef ENABLE_WSTK_LEDS
+#include "LEDWidget.h"
+#define APP_ACTION_LED 1
+#endif // ENABLE_WSTK_LEDS
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+namespace {
+
+#ifdef ENABLE_WSTK_LEDS
+LEDWidget sLightLED;
+#endif // ENABLE_WSTK_LEDS
+
+EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+/**********************************************************
+ * Identify Callbacks
+ *********************************************************/
+
+namespace {
+void OnTriggerIdentifyEffectCompleted(chip::System::Layer * systemLayer, void * appState)
+{
+ ChipLogProgress(Zcl, "Trigger Identify Complete");
+ sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ AppTask::GetAppTask().StopStatusLEDTimer();
+#endif
+}
+} // namespace
+
+#ifdef DIC_ENABLE
+namespace {
+void AppSpecificConnectivityEventCallback(const ChipDeviceEvent * event, intptr_t arg)
+{
+ SILABS_LOG("AppSpecificConnectivityEventCallback: call back for IPV4");
+ if ((event->Type == DeviceEventType::kInternetConnectivityChange) &&
+ (event->InternetConnectivityChange.IPv4 == kConnectivity_Established))
+ {
+ SILABS_LOG("Got IPv4 Address! Starting DIC module\n");
+ if (DIC_OK != DIC_Init())
+ SILABS_LOG("Failed to initialize DIC module\n");
+ }
+}
+}
+#endif
+
+void OnTriggerIdentifyEffect(Identify * identify)
+{
+ sIdentifyEffect = identify->mCurrentEffectIdentifier;
+
+ if (identify->mCurrentEffectIdentifier == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE)
+ {
+ ChipLogProgress(Zcl, "IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE - Not supported, use effect varriant %d",
+ identify->mEffectVariant);
+ sIdentifyEffect = static_cast(identify->mEffectVariant);
+ }
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ AppTask::GetAppTask().StartStatusLEDTimer();
+#endif
+
+ switch (sIdentifyEffect)
+ {
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK:
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE:
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY:
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(5), OnTriggerIdentifyEffectCompleted,
+ identify);
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT:
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(1), OnTriggerIdentifyEffectCompleted,
+ identify);
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT:
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+ break;
+ default:
+ ChipLogProgress(Zcl, "No identifier effect");
+ }
+}
+
+Identify gIdentify = {
+ chip::EndpointId{ 1 },
+ AppTask::GetAppTask().OnIdentifyStart,
+ AppTask::GetAppTask().OnIdentifyStop,
+ EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED,
+ OnTriggerIdentifyEffect,
+};
+
+} // namespace
+
+using namespace chip::TLV;
+using namespace ::chip::DeviceLayer;
+
+AppTask AppTask::sAppTask;
+
+CHIP_ERROR AppTask::Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+#ifdef DISPLAY_ENABLED
+ GetLCD().Init((uint8_t *) "Lighting-App");
+#endif
+
+ err = BaseApplication::Init(&gIdentify);
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("BaseApplication::Init() failed");
+ appError(err);
+ }
+
+ err = LightMgr().Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("LightMgr::Init() failed");
+ appError(err);
+ }
+
+ LightMgr().SetCallbacks(ActionInitiated, ActionCompleted);
+#ifdef DIC_ENABLE
+ chip::DeviceLayer::PlatformMgr().AddEventHandler(AppSpecificConnectivityEventCallback, reinterpret_cast(nullptr));
+#endif
+
+#ifdef ENABLE_WSTK_LEDS
+ sLightLED.Init(APP_ACTION_LED);
+ sLightLED.Set(LightMgr().IsLightOn());
+#endif // ENABLE_WSTK_LEDS
+
+ return err;
+}
+
+CHIP_ERROR AppTask::StartAppTask()
+{
+ return BaseApplication::StartAppTask(AppTaskMain);
+}
+
+void AppTask::AppTaskMain(void * pvParameter)
+{
+ AppEvent event;
+ QueueHandle_t sAppEventQueue = *(static_cast(pvParameter));
+
+ CHIP_ERROR err = sAppTask.Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("AppTask.Init() failed");
+ appError(err);
+ }
+
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+ sAppTask.StartStatusLEDTimer();
+#endif
+
+ SILABS_LOG("App Task started");
+
+ while (true)
+ {
+ BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, pdMS_TO_TICKS(10));
+ while (eventReceived == pdTRUE)
+ {
+ sAppTask.DispatchEvent(&event);
+ eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
+ }
+ }
+}
+
+void AppTask::OnIdentifyStart(Identify * identify)
+{
+ ChipLogProgress(Zcl, "onIdentifyStart");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ sAppTask.StartStatusLEDTimer();
+#endif
+}
+
+void AppTask::OnIdentifyStop(Identify * identify)
+{
+ ChipLogProgress(Zcl, "onIdentifyStop");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ sAppTask.StopStatusLEDTimer();
+#endif
+}
+
+void AppTask::LightActionEventHandler(AppEvent * aEvent)
+{
+ bool initiated = false;
+ LightingManager::Action_t action;
+ int32_t actor;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ if (aEvent->Type == AppEvent::kEventType_Light)
+ {
+ action = static_cast(aEvent->LightEvent.Action);
+ actor = aEvent->LightEvent.Actor;
+ }
+ else if (aEvent->Type == AppEvent::kEventType_Button)
+ {
+ action = (LightMgr().IsLightOn()) ? LightingManager::OFF_ACTION : LightingManager::ON_ACTION;
+ actor = AppEvent::kEventType_Button;
+ }
+ else
+ {
+ err = APP_ERROR_UNHANDLED_EVENT;
+ }
+
+ if (err == CHIP_NO_ERROR)
+ {
+ initiated = LightMgr().InitiateAction(actor, action);
+
+ if (!initiated)
+ {
+ SILABS_LOG("Action is already in progress or active.");
+ }
+ }
+}
+
+void AppTask::ButtonEventHandler(uint8_t button, uint8_t btnAction)
+{
+ AppEvent button_event = {};
+ button_event.Type = AppEvent::kEventType_Button;
+ button_event.ButtonEvent.Action = btnAction;
+ if (button == SIWx917_BTN1 && btnAction == SL_SIMPLE_BUTTON_PRESSED)
+ {
+ button_event.Handler = LightActionEventHandler;
+ sAppTask.PostEvent(&button_event);
+ }
+ else if (button == SIWx917_BTN0)
+ {
+ button_event.Handler = BaseApplication::ButtonHandler;
+ sAppTask.PostEvent(&button_event);
+ }
+}
+
+void AppTask::ActionInitiated(LightingManager::Action_t aAction, int32_t aActor)
+{
+ // Action initiated, update the light led
+ bool lightOn = aAction == LightingManager::ON_ACTION;
+ SILABS_LOG("Turning light %s", (lightOn) ? "On" : "Off");
+ sLightLED.Set(lightOn);
+
+#ifdef DISPLAY_ENABLED
+ sAppTask.GetLCD().WriteDemoUI(lightOn);
+#endif
+
+ if (aActor == AppEvent::kEventType_Button)
+ {
+ sAppTask.mSyncClusterToButtonAction = true;
+ }
+}
+
+void AppTask::ActionCompleted(LightingManager::Action_t aAction)
+{
+ // action has been completed bon the light
+ if (aAction == LightingManager::ON_ACTION)
+ {
+ SILABS_LOG("Light ON")
+ }
+ else if (aAction == LightingManager::OFF_ACTION)
+ {
+ SILABS_LOG("Light OFF")
+ }
+
+ if (sAppTask.mSyncClusterToButtonAction)
+ {
+ chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterState, reinterpret_cast(nullptr));
+ sAppTask.mSyncClusterToButtonAction = false;
+ }
+}
+
+void AppTask::PostLightActionRequest(int32_t aActor, LightingManager::Action_t aAction)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Light;
+ event.LightEvent.Actor = aActor;
+ event.LightEvent.Action = aAction;
+ event.Handler = LightActionEventHandler;
+ PostEvent(&event);
+}
+
+void AppTask::UpdateClusterState(intptr_t context)
+{
+ uint8_t newValue = LightMgr().IsLightOn();
+
+ // write the new on/off value
+ EmberAfStatus status = OnOffServer::Instance().setOnOffValue(1, newValue, false);
+
+ if (status != EMBER_ZCL_STATUS_SUCCESS)
+ {
+ SILABS_LOG("ERR: updating on/off %x", status);
+ }
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/LightingManager.cpp b/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/LightingManager.cpp
new file mode 100644
index 00000000000000..2c5807f4ea693e
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/LightingManager.cpp
@@ -0,0 +1,322 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LightingManager.h"
+
+#include "AppConfig.h"
+#include "AppTask.h"
+#include
+
+#include
+
+using namespace chip;
+using namespace ::chip::app::Clusters::OnOff;
+using namespace ::chip::DeviceLayer;
+
+LightingManager LightingManager::sLight;
+
+TimerHandle_t sLightTimer;
+
+namespace {
+
+/**********************************************************
+ * OffWithEffect Callbacks
+ *********************************************************/
+
+OnOffEffect gEffect = {
+ chip::EndpointId{ 1 },
+ LightMgr().OnTriggerOffWithEffect,
+ OnOffEffectIdentifier::kDelayedAllOff,
+ to_underlying(OnOffDelayedAllOffEffectVariant::kFadeToOffIn0p8Seconds),
+};
+
+} // namespace
+
+CHIP_ERROR LightingManager::Init()
+{
+ // Create FreeRTOS sw timer for light timer.
+ sLightTimer = xTimerCreate("lightTmr", // Just a text name, not used by the RTOS kernel
+ pdMS_TO_TICKS(1), // == default timer period
+ false, // no timer reload (==one-shot)
+ (void *) this, // init timer id = light obj context
+ TimerEventHandler // timer callback handler
+ );
+
+ if (sLightTimer == NULL)
+ {
+ SILABS_LOG("sLightTimer timer create failed");
+ return APP_ERROR_CREATE_TIMER_FAILED;
+ }
+
+ bool currentLedState;
+ // read current on/off value on endpoint one.
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ OnOffServer::Instance().getOnOffValue(1, ¤tLedState);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ mState = currentLedState ? kState_OnCompleted : kState_OffCompleted;
+ mAutoTurnOffTimerArmed = false;
+ mAutoTurnOff = false;
+ mAutoTurnOffDuration = 0;
+ mOffEffectArmed = false;
+
+ return CHIP_NO_ERROR;
+}
+
+void LightingManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
+{
+ mActionInitiated_CB = aActionInitiated_CB;
+ mActionCompleted_CB = aActionCompleted_CB;
+}
+
+bool LightingManager::IsActionInProgress()
+{
+ return (mState == kState_OffInitiated || mState == kState_OnInitiated);
+}
+
+bool LightingManager::IsLightOn()
+{
+ return (mState == kState_OnCompleted);
+}
+
+void LightingManager::EnableAutoTurnOff(bool aOn)
+{
+ mAutoTurnOff = aOn;
+}
+
+void LightingManager::SetAutoTurnOffDuration(uint32_t aDurationInSecs)
+{
+ mAutoTurnOffDuration = aDurationInSecs;
+}
+
+bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction)
+{
+ bool action_initiated = false;
+ State_t new_state;
+
+ // Initiate Turn On/Off Action only when the previous one is complete.
+ if (((mState == kState_OffCompleted) || mOffEffectArmed) && aAction == ON_ACTION)
+ {
+ action_initiated = true;
+
+ new_state = kState_OnInitiated;
+ }
+ else if (mState == kState_OnCompleted && aAction == OFF_ACTION && mOffEffectArmed == false)
+ {
+ action_initiated = true;
+
+ new_state = kState_OffInitiated;
+ }
+
+ if (action_initiated)
+ {
+ if (mAutoTurnOffTimerArmed && new_state == kState_OffInitiated)
+ {
+ // If auto turn off timer has been armed and someone initiates turning off,
+ // cancel the timer and continue as normal.
+ mAutoTurnOffTimerArmed = false;
+
+ CancelTimer();
+ }
+
+ if (mOffEffectArmed && new_state == kState_OnInitiated)
+ {
+ CancelTimer();
+ mOffEffectArmed = false;
+ }
+
+ StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
+
+ // Since the timer started successfully, update the state and trigger callback
+ mState = new_state;
+
+ if (mActionInitiated_CB)
+ {
+ mActionInitiated_CB(aAction, aActor);
+ }
+ }
+
+ return action_initiated;
+}
+
+void LightingManager::StartTimer(uint32_t aTimeoutMs)
+{
+ if (xTimerIsTimerActive(sLightTimer))
+ {
+ SILABS_LOG("app timer already started!");
+ CancelTimer();
+ }
+
+ // timer is not active, change its period to required value (== restart).
+ // FreeRTOS- Block for a maximum of 100 ms if the change period command
+ // cannot immediately be sent to the timer command queue.
+ if (xTimerChangePeriod(sLightTimer, pdMS_TO_TICKS(aTimeoutMs), pdMS_TO_TICKS(100)) != pdPASS)
+ {
+ SILABS_LOG("sLightTimer timer start() failed");
+ appError(APP_ERROR_START_TIMER_FAILED);
+ }
+}
+
+void LightingManager::CancelTimer(void)
+{
+ if (xTimerStop(sLightTimer, pdMS_TO_TICKS(0)) == pdFAIL)
+ {
+ SILABS_LOG("sLightTimer stop() failed");
+ appError(APP_ERROR_STOP_TIMER_FAILED);
+ }
+}
+
+void LightingManager::TimerEventHandler(TimerHandle_t xTimer)
+{
+ // Get light obj context from timer id.
+ LightingManager * light = static_cast(pvTimerGetTimerID(xTimer));
+
+ // The timer event handler will be called in the context of the timer task
+ // once sLightTimer expires. Post an event to apptask queue with the actual handler
+ // so that the event can be handled in the context of the apptask.
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.Context = light;
+ if (light->mAutoTurnOffTimerArmed)
+ {
+ event.Handler = AutoTurnOffTimerEventHandler;
+ }
+ else if (light->mOffEffectArmed)
+ {
+ event.Handler = OffEffectTimerEventHandler;
+ }
+ else
+ {
+ event.Handler = ActuatorMovementTimerEventHandler;
+ }
+ AppTask::GetAppTask().PostEvent(&event);
+}
+
+void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent)
+{
+ LightingManager * light = static_cast(aEvent->TimerEvent.Context);
+ int32_t actor = AppEvent::kEventType_Timer;
+
+ // Make sure auto turn off timer is still armed.
+ if (!light->mAutoTurnOffTimerArmed)
+ {
+ return;
+ }
+
+ light->mAutoTurnOffTimerArmed = false;
+
+ SILABS_LOG("Auto Turn Off has been triggered!");
+
+ light->InitiateAction(actor, OFF_ACTION);
+}
+
+void LightingManager::OffEffectTimerEventHandler(AppEvent * aEvent)
+{
+ LightingManager * light = static_cast(aEvent->TimerEvent.Context);
+ int32_t actor = AppEvent::kEventType_Timer;
+
+ // Make sure auto turn off timer is still armed.
+ if (!light->mOffEffectArmed)
+ {
+ return;
+ }
+
+ light->mOffEffectArmed = false;
+
+ SILABS_LOG("OffEffect completed");
+
+ light->InitiateAction(actor, OFF_ACTION);
+}
+
+void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
+{
+ Action_t actionCompleted = INVALID_ACTION;
+
+ LightingManager * light = static_cast(aEvent->TimerEvent.Context);
+
+ if (light->mState == kState_OffInitiated)
+ {
+ light->mState = kState_OffCompleted;
+ actionCompleted = OFF_ACTION;
+ }
+ else if (light->mState == kState_OnInitiated)
+ {
+ light->mState = kState_OnCompleted;
+ actionCompleted = ON_ACTION;
+ }
+
+ if (actionCompleted != INVALID_ACTION)
+ {
+ if (light->mActionCompleted_CB)
+ {
+ light->mActionCompleted_CB(actionCompleted);
+ }
+
+ if (light->mAutoTurnOff && actionCompleted == ON_ACTION)
+ {
+ // Start the timer for auto turn off
+ light->StartTimer(light->mAutoTurnOffDuration * 1000);
+
+ light->mAutoTurnOffTimerArmed = true;
+
+ SILABS_LOG("Auto Turn off enabled. Will be triggered in %u seconds", light->mAutoTurnOffDuration);
+ }
+ }
+}
+
+void LightingManager::OnTriggerOffWithEffect(OnOffEffect * effect)
+{
+ auto effectId = effect->mEffectIdentifier;
+ auto effectVariant = effect->mEffectVariant;
+ uint32_t offEffectDuration = 0;
+
+ // Temporary print outs and delay to test OffEffect behaviour
+ // Until dimming is supported for dev boards.
+ if (effectId == OnOffEffectIdentifier::kDelayedAllOff)
+ {
+ auto typedEffectVariant = static_cast(effectVariant);
+ if (typedEffectVariant == OnOffDelayedAllOffEffectVariant::kFadeToOffIn0p8Seconds)
+ {
+ offEffectDuration = 800;
+ ChipLogProgress(Zcl, "OnOffDelayedAllOffEffectVariant::kFadeToOffIn0p8Seconds");
+ }
+ else if (typedEffectVariant == OnOffDelayedAllOffEffectVariant::kNoFade)
+ {
+ offEffectDuration = 800;
+ ChipLogProgress(Zcl, "OnOffDelayedAllOffEffectVariant::kNoFade");
+ }
+ else if (typedEffectVariant == OnOffDelayedAllOffEffectVariant::k50PercentDimDownIn0p8SecondsThenFadeToOffIn12Seconds)
+ {
+ offEffectDuration = 12800;
+ ChipLogProgress(Zcl, "OnOffDelayedAllOffEffectVariant::k50PercentDimDownIn0p8SecondsThenFadeToOffIn12Seconds");
+ }
+ }
+ else if (effectId == OnOffEffectIdentifier::kDyingLight)
+ {
+ auto typedEffectVariant = static_cast(effectVariant);
+ if (typedEffectVariant == OnOffDyingLightEffectVariant::k20PercenterDimUpIn0p5SecondsThenFadeToOffIn1Second)
+ {
+ offEffectDuration = 1500;
+ ChipLogProgress(Zcl, "OnOffDyingLightEffectVariant::k20PercenterDimUpIn0p5SecondsThenFadeToOffIn1Second");
+ }
+ }
+
+ LightMgr().mOffEffectArmed = true;
+ LightMgr().StartTimer(offEffectDuration);
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/ZclCallbacks.cpp b/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/ZclCallbacks.cpp
new file mode 100644
index 00000000000000..4114d80c89b39d
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/ZclCallbacks.cpp
@@ -0,0 +1,104 @@
+/*
+ *
+ * Copyright (c) 2020 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.
+ */
+
+/**
+ * @file
+ * This file implements the handler for data model messages.
+ */
+
+#include "AppConfig.h"
+#include "LightingManager.h"
+
+#ifdef DIC_ENABLE
+#include "dic.h"
+#endif
+
+#include
+#include
+#include
+#include
+
+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));
+#ifdef DIC_ENABLE
+ if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
+ {
+ dic_buff_t buffValue;
+
+ buffValue.dataP = (uint8_t *)(value ? ( *value ? "on" : "off") : "invalid");
+ buffValue.dataLen = strlen((const char *)buffValue.dataP);
+ DIC_SendMsg("light/state", &buffValue);
+ }
+#endif
+ if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
+ {
+ LightMgr().InitiateAction(AppEvent::kEventType_Light, *value ? LightingManager::ON_ACTION : LightingManager::OFF_ACTION);
+ }
+ else if (clusterId == LevelControl::Id)
+ {
+ ChipLogProgress(Zcl, "Level Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (clusterId == ColorControl::Id)
+ {
+ ChipLogProgress(Zcl, "Color Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (clusterId == OnOffSwitchConfiguration::Id)
+ {
+ ChipLogProgress(Zcl, "OnOff Switch Configuration attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (clusterId == Identify::Id)
+ {
+ 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
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/main.cpp b/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/main.cpp
new file mode 100644
index 00000000000000..d95f6b7ab51295
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/src/main.cpp
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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
+
+#include "AppConfig.h"
+#include "init_ccpPlatform.h"
+
+#include
+#include
+#include
+#include
+#ifdef SI917_ATTESTATION_CREDENTIALS
+#include
+#else
+#include
+#endif
+
+#define BLE_DEV_NAME "SiLabs-Light"
+
+extern "C" void sl_button_on_change(uint8_t btn, uint8_t btnAction);
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::Credentials;
+
+#define UNUSED_PARAMETER(a) (a = a)
+
+volatile int apperror_cnt;
+static chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+
+// ================================================================================
+// Main Code
+// ================================================================================
+int main(void)
+{
+ init_ccpPlatform();
+ if (SI917MatterConfig::InitMatter(BLE_DEV_NAME) != CHIP_NO_ERROR)
+ {
+ appError(CHIP_ERROR_INTERNAL);
+ }
+
+ gExampleDeviceInfoProvider.SetStorageDelegate(&chip::Server::GetInstance().GetPersistentStorage());
+ chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ // Initialize device attestation config
+#ifdef SI917_ATTESTATION_CREDENTIALS
+ SetDeviceAttestationCredentialsProvider(Silabs::GetSilabsDacProvider());
+#else
+ SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ SILABS_LOG("Starting App Task");
+ if (AppTask::GetAppTask().StartAppTask() != CHIP_NO_ERROR)
+ {
+ appError(CHIP_ERROR_INTERNAL);
+ }
+
+ SILABS_LOG("Starting FreeRTOS scheduler");
+ vTaskStartScheduler();
+
+ // Should never get here.
+ chip::Platform::MemoryShutdown();
+ SILABS_LOG("vTaskStartScheduler() failed");
+ appError(CHIP_ERROR_INTERNAL);
+}
+
+void sl_button_on_change(uint8_t btn, uint8_t btnAction)
+{
+ AppTask::GetAppTask().ButtonEventHandler(btn, btnAction);
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/third_party/connectedhomeip b/silabs_examples/Direct_Internet_lighting-app/SiWx917/third_party/connectedhomeip
new file mode 120000
index 00000000000000..c866b86874994d
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../..
\ No newline at end of file
diff --git a/silabs_examples/Direct_Internet_lighting-app/SiWx917/with_pw_rpc.gni b/silabs_examples/Direct_Internet_lighting-app/SiWx917/with_pw_rpc.gni
new file mode 100644
index 00000000000000..1621fbd98ea74a
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/SiWx917/with_pw_rpc.gni
@@ -0,0 +1,31 @@
+# Copyright (c) 2021 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.
+
+# add this gni as import in your build args to use pigweed in the example
+# 'import("//with_pw_rpc.gni")'
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/efr32/lib/pw_rpc/pw_rpc.gni")
+import("${chip_root}/examples/platform/silabs/SiWx917/args.gni")
+
+siwx917_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_pw_rpc = true
+chip_enable_openthread = true
+chip_build_pw_trace_lib = true
+
+cpp_standard = "gnu++17"
+
+# Light app on EFR enables tracing server
+pw_trace_BACKEND = "$dir_pw_trace_tokenized"
diff --git a/silabs_examples/Direct_Internet_lighting-app/data_model/BUILD.gn b/silabs_examples/Direct_Internet_lighting-app/data_model/BUILD.gn
new file mode 100644
index 00000000000000..654e9414f831aa
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/data_model/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright (c) 2020 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.
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/src/app/chip_data_model.gni")
+import("${chip_root}/src/platform/device.gni")
+
+chip_data_model("silabs-lighting") {
+ zap_file = "lighting-wifi-app.zap"
+
+ zap_pregenerated_dir = "${chip_root}/zzz_generated/Direct_Internet_lighting-app/zap-generated"
+ is_server = true
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/data_model/lighting-wifi-app.matter b/silabs_examples/Direct_Internet_lighting-app/data_model/lighting-wifi-app.matter
new file mode 100644
index 00000000000000..0ca16845849b6a
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/data_model/lighting-wifi-app.matter
@@ -0,0 +1,1837 @@
+// This IDL was generated automatically by ZAP.
+// It is for view/code review purposes only.
+
+struct LabelStruct {
+ char_string<16> label = 0;
+ char_string<16> value = 1;
+}
+
+server cluster Identify = 3 {
+ enum IdentifyEffectIdentifier : ENUM8 {
+ kBlink = 0;
+ kBreathe = 1;
+ kOkay = 2;
+ kChannelChange = 11;
+ kFinishEffect = 254;
+ kStopEffect = 255;
+ }
+
+ enum IdentifyEffectVariant : ENUM8 {
+ kDefault = 0;
+ }
+
+ enum IdentifyIdentifyType : ENUM8 {
+ kNone = 0;
+ kVisibleLight = 1;
+ kVisibleLED = 2;
+ kAudibleBeep = 3;
+ kDisplay = 4;
+ kActuator = 5;
+ }
+
+ attribute int16u identifyTime = 0;
+ readonly attribute enum8 identifyType = 1;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct IdentifyRequest {
+ INT16U identifyTime = 0;
+ }
+
+ request struct TriggerEffectRequest {
+ IdentifyEffectIdentifier effectIdentifier = 0;
+ IdentifyEffectVariant effectVariant = 1;
+ }
+
+ command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0;
+ command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64;
+}
+
+server cluster Groups = 4 {
+ bitmap GroupClusterFeature : BITMAP32 {
+ kGroupNames = 0x1;
+ }
+
+ readonly attribute bitmap8 nameSupport = 0;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct AddGroupRequest {
+ group_id groupID = 0;
+ CHAR_STRING groupName = 1;
+ }
+
+ request struct ViewGroupRequest {
+ group_id groupID = 0;
+ }
+
+ request struct GetGroupMembershipRequest {
+ group_id groupList[] = 0;
+ }
+
+ request struct RemoveGroupRequest {
+ group_id groupID = 0;
+ }
+
+ request struct AddGroupIfIdentifyingRequest {
+ group_id groupID = 0;
+ CHAR_STRING groupName = 1;
+ }
+
+ response struct AddGroupResponse = 0 {
+ ENUM8 status = 0;
+ group_id groupID = 1;
+ }
+
+ response struct ViewGroupResponse = 1 {
+ ENUM8 status = 0;
+ group_id groupID = 1;
+ CHAR_STRING groupName = 2;
+ }
+
+ response struct GetGroupMembershipResponse = 2 {
+ nullable INT8U capacity = 0;
+ group_id groupList[] = 1;
+ }
+
+ response struct RemoveGroupResponse = 3 {
+ ENUM8 status = 0;
+ group_id groupID = 1;
+ }
+
+ fabric command access(invoke: manage) AddGroup(AddGroupRequest): AddGroupResponse = 0;
+ fabric command ViewGroup(ViewGroupRequest): ViewGroupResponse = 1;
+ fabric command GetGroupMembership(GetGroupMembershipRequest): GetGroupMembershipResponse = 2;
+ fabric command access(invoke: manage) RemoveGroup(RemoveGroupRequest): RemoveGroupResponse = 3;
+ fabric command access(invoke: manage) RemoveAllGroups(): DefaultSuccess = 4;
+ fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5;
+}
+
+server cluster OnOff = 6 {
+ enum OnOffDelayedAllOffEffectVariant : ENUM8 {
+ kFadeToOffIn0p8Seconds = 0;
+ kNoFade = 1;
+ k50PercentDimDownIn0p8SecondsThenFadeToOffIn12Seconds = 2;
+ }
+
+ enum OnOffDyingLightEffectVariant : ENUM8 {
+ k20PercenterDimUpIn0p5SecondsThenFadeToOffIn1Second = 0;
+ }
+
+ enum OnOffEffectIdentifier : ENUM8 {
+ kDelayedAllOff = 0;
+ kDyingLight = 1;
+ }
+
+ enum OnOffStartUpOnOff : ENUM8 {
+ kOff = 0;
+ kOn = 1;
+ kTogglePreviousOnOff = 2;
+ }
+
+ bitmap OnOffControl : BITMAP8 {
+ kAcceptOnlyWhenOn = 0x1;
+ }
+
+ bitmap OnOffFeature : BITMAP32 {
+ kLighting = 0x1;
+ }
+
+ readonly attribute boolean onOff = 0;
+ readonly attribute boolean globalSceneControl = 16384;
+ attribute int16u onTime = 16385;
+ attribute int16u offWaitTime = 16386;
+ attribute access(write: manage) nullable OnOffStartUpOnOff startUpOnOff = 16387;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct OffWithEffectRequest {
+ OnOffEffectIdentifier effectIdentifier = 0;
+ int8u effectVariant = 1;
+ }
+
+ request struct OnWithTimedOffRequest {
+ OnOffControl onOffControl = 0;
+ int16u onTime = 1;
+ int16u offWaitTime = 2;
+ }
+
+ command Off(): DefaultSuccess = 0;
+ command On(): DefaultSuccess = 1;
+ command Toggle(): DefaultSuccess = 2;
+ command OffWithEffect(OffWithEffectRequest): DefaultSuccess = 64;
+ command OnWithRecallGlobalScene(): DefaultSuccess = 65;
+ command OnWithTimedOff(OnWithTimedOffRequest): DefaultSuccess = 66;
+}
+
+server cluster LevelControl = 8 {
+ enum MoveMode : ENUM8 {
+ kUp = 0;
+ kDown = 1;
+ }
+
+ enum StepMode : ENUM8 {
+ kUp = 0;
+ kDown = 1;
+ }
+
+ bitmap LevelControlFeature : BITMAP32 {
+ kOnOff = 0x1;
+ kLighting = 0x2;
+ kFrequency = 0x4;
+ }
+
+ bitmap LevelControlOptions : BITMAP8 {
+ kExecuteIfOff = 0x1;
+ kCoupleColorTempToLevel = 0x2;
+ }
+
+ readonly attribute nullable int8u currentLevel = 0;
+ readonly attribute int16u remainingTime = 1;
+ readonly attribute int8u minLevel = 2;
+ readonly attribute int8u maxLevel = 3;
+ readonly attribute int16u currentFrequency = 4;
+ readonly attribute int16u minFrequency = 5;
+ readonly attribute int16u maxFrequency = 6;
+ attribute LevelControlOptions options = 15;
+ attribute int16u onOffTransitionTime = 16;
+ attribute nullable int8u onLevel = 17;
+ attribute nullable int16u onTransitionTime = 18;
+ attribute nullable int16u offTransitionTime = 19;
+ attribute nullable int8u defaultMoveRate = 20;
+ attribute access(write: manage) nullable int8u startUpCurrentLevel = 16384;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct MoveToLevelRequest {
+ INT8U level = 0;
+ nullable INT16U transitionTime = 1;
+ LevelControlOptions optionsMask = 2;
+ LevelControlOptions optionsOverride = 3;
+ }
+
+ request struct MoveRequest {
+ MoveMode moveMode = 0;
+ nullable INT8U rate = 1;
+ LevelControlOptions optionsMask = 2;
+ LevelControlOptions optionsOverride = 3;
+ }
+
+ request struct StepRequest {
+ StepMode stepMode = 0;
+ INT8U stepSize = 1;
+ nullable INT16U transitionTime = 2;
+ LevelControlOptions optionsMask = 3;
+ LevelControlOptions optionsOverride = 4;
+ }
+
+ request struct StopRequest {
+ LevelControlOptions optionsMask = 0;
+ LevelControlOptions optionsOverride = 1;
+ }
+
+ request struct MoveToLevelWithOnOffRequest {
+ INT8U level = 0;
+ nullable INT16U transitionTime = 1;
+ LevelControlOptions optionsMask = 2;
+ LevelControlOptions optionsOverride = 3;
+ }
+
+ request struct MoveWithOnOffRequest {
+ MoveMode moveMode = 0;
+ nullable INT8U rate = 1;
+ LevelControlOptions optionsMask = 2;
+ LevelControlOptions optionsOverride = 3;
+ }
+
+ request struct StepWithOnOffRequest {
+ StepMode stepMode = 0;
+ INT8U stepSize = 1;
+ nullable INT16U transitionTime = 2;
+ LevelControlOptions optionsMask = 3;
+ LevelControlOptions optionsOverride = 4;
+ }
+
+ request struct StopWithOnOffRequest {
+ LevelControlOptions optionsMask = 0;
+ LevelControlOptions optionsOverride = 1;
+ }
+
+ command MoveToLevel(MoveToLevelRequest): DefaultSuccess = 0;
+ command Move(MoveRequest): DefaultSuccess = 1;
+ command Step(StepRequest): DefaultSuccess = 2;
+ command Stop(StopRequest): DefaultSuccess = 3;
+ command MoveToLevelWithOnOff(MoveToLevelWithOnOffRequest): DefaultSuccess = 4;
+ command MoveWithOnOff(MoveWithOnOffRequest): DefaultSuccess = 5;
+ command StepWithOnOff(StepWithOnOffRequest): DefaultSuccess = 6;
+ command StopWithOnOff(StopWithOnOffRequest): DefaultSuccess = 7;
+}
+
+server cluster Descriptor = 29 {
+ struct DeviceTypeStruct {
+ devtype_id deviceType = 0;
+ int16u revision = 1;
+ }
+
+ readonly attribute DeviceTypeStruct deviceTypeList[] = 0;
+ readonly attribute CLUSTER_ID serverList[] = 1;
+ readonly attribute CLUSTER_ID clientList[] = 2;
+ readonly attribute ENDPOINT_NO partsList[] = 3;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+}
+
+server cluster AccessControl = 31 {
+ enum AccessControlEntryAuthModeEnum : ENUM8 {
+ kPase = 1;
+ kCase = 2;
+ kGroup = 3;
+ }
+
+ enum AccessControlEntryPrivilegeEnum : ENUM8 {
+ kView = 1;
+ kProxyView = 2;
+ kOperate = 3;
+ kManage = 4;
+ kAdminister = 5;
+ }
+
+ enum ChangeTypeEnum : ENUM8 {
+ kChanged = 0;
+ kAdded = 1;
+ kRemoved = 2;
+ }
+
+ fabric_scoped struct AccessControlEntryStruct {
+ fabric_sensitive AccessControlEntryPrivilegeEnum privilege = 1;
+ fabric_sensitive AccessControlEntryAuthModeEnum authMode = 2;
+ nullable fabric_sensitive int64u subjects[] = 3;
+ nullable fabric_sensitive Target targets[] = 4;
+ fabric_idx fabricIndex = 254;
+ }
+
+ struct Target {
+ nullable cluster_id cluster = 0;
+ nullable endpoint_no endpoint = 1;
+ nullable devtype_id deviceType = 2;
+ }
+
+ fabric_scoped struct AccessControlExtensionStruct {
+ fabric_sensitive octet_string<128> data = 1;
+ fabric_idx fabricIndex = 254;
+ }
+
+ fabric_sensitive info event access(read: administer) AccessControlEntryChanged = 0 {
+ nullable node_id adminNodeID = 1;
+ nullable INT16U adminPasscodeID = 2;
+ ChangeTypeEnum changeType = 3;
+ nullable AccessControlEntryStruct latestValue = 4;
+ fabric_idx fabricIndex = 254;
+ }
+
+ fabric_sensitive info event access(read: administer) AccessControlExtensionChanged = 1 {
+ nullable node_id adminNodeID = 1;
+ nullable INT16U adminPasscodeID = 2;
+ ChangeTypeEnum changeType = 3;
+ nullable AccessControlExtensionStruct latestValue = 4;
+ fabric_idx fabricIndex = 254;
+ }
+
+ attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0;
+ attribute access(read: administer, write: administer) AccessControlExtensionStruct extension[] = 1;
+ readonly attribute int16u subjectsPerAccessControlEntry = 2;
+ readonly attribute int16u targetsPerAccessControlEntry = 3;
+ readonly attribute int16u accessControlEntriesPerFabric = 4;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+}
+
+server cluster BasicInformation = 40 {
+ struct CapabilityMinimaStruct {
+ int16u caseSessionsPerFabric = 0;
+ int16u subscriptionsPerFabric = 1;
+ }
+
+ critical event StartUp = 0 {
+ INT32U softwareVersion = 0;
+ }
+
+ critical event ShutDown = 1 {
+ }
+
+ info event Leave = 2 {
+ fabric_idx fabricIndex = 0;
+ }
+
+ info event ReachableChanged = 3 {
+ boolean reachableNewValue = 0;
+ }
+
+ readonly attribute int16u dataModelRevision = 0;
+ readonly attribute char_string<32> vendorName = 1;
+ readonly attribute vendor_id vendorID = 2;
+ readonly attribute char_string<32> productName = 3;
+ readonly attribute int16u productID = 4;
+ attribute access(write: manage) char_string<32> nodeLabel = 5;
+ attribute access(write: administer) char_string<2> location = 6;
+ readonly attribute int16u hardwareVersion = 7;
+ readonly attribute char_string<64> hardwareVersionString = 8;
+ readonly attribute int32u softwareVersion = 9;
+ readonly attribute char_string<64> softwareVersionString = 10;
+ readonly attribute char_string<16> manufacturingDate = 11;
+ readonly attribute char_string<32> partNumber = 12;
+ readonly attribute long_char_string<256> productURL = 13;
+ readonly attribute char_string<64> productLabel = 14;
+ readonly attribute char_string<32> serialNumber = 15;
+ attribute access(write: manage) boolean localConfigDisabled = 16;
+ readonly attribute boolean reachable = 17;
+ readonly attribute char_string<32> uniqueID = 18;
+ readonly attribute CapabilityMinimaStruct capabilityMinima = 19;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+}
+
+client cluster OtaSoftwareUpdateProvider = 41 {
+ enum OTAApplyUpdateAction : ENUM8 {
+ kProceed = 0;
+ kAwaitNextAction = 1;
+ kDiscontinue = 2;
+ }
+
+ enum OTADownloadProtocol : ENUM8 {
+ kBDXSynchronous = 0;
+ kBDXAsynchronous = 1;
+ kHttps = 2;
+ kVendorSpecific = 3;
+ }
+
+ enum OTAQueryStatus : ENUM8 {
+ kUpdateAvailable = 0;
+ kBusy = 1;
+ kNotAvailable = 2;
+ kDownloadProtocolNotSupported = 3;
+ }
+
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct QueryImageRequest {
+ vendor_id vendorID = 0;
+ INT16U productID = 1;
+ INT32U softwareVersion = 2;
+ OTADownloadProtocol protocolsSupported[] = 3;
+ optional INT16U hardwareVersion = 4;
+ optional CHAR_STRING<2> location = 5;
+ optional BOOLEAN requestorCanConsent = 6;
+ optional OCTET_STRING<512> metadataForProvider = 7;
+ }
+
+ request struct ApplyUpdateRequestRequest {
+ OCTET_STRING<32> updateToken = 0;
+ INT32U newVersion = 1;
+ }
+
+ request struct NotifyUpdateAppliedRequest {
+ OCTET_STRING<32> updateToken = 0;
+ INT32U softwareVersion = 1;
+ }
+
+ response struct QueryImageResponse = 1 {
+ OTAQueryStatus status = 0;
+ optional INT32U delayedActionTime = 1;
+ optional CHAR_STRING<256> imageURI = 2;
+ optional INT32U softwareVersion = 3;
+ optional CHAR_STRING<64> softwareVersionString = 4;
+ optional OCTET_STRING<32> updateToken = 5;
+ optional BOOLEAN userConsentNeeded = 6;
+ optional OCTET_STRING<512> metadataForRequestor = 7;
+ }
+
+ response struct ApplyUpdateResponse = 3 {
+ OTAApplyUpdateAction action = 0;
+ INT32U delayedActionTime = 1;
+ }
+
+ command QueryImage(QueryImageRequest): QueryImageResponse = 0;
+ command ApplyUpdateRequest(ApplyUpdateRequestRequest): ApplyUpdateResponse = 2;
+ command NotifyUpdateApplied(NotifyUpdateAppliedRequest): DefaultSuccess = 4;
+}
+
+server cluster OtaSoftwareUpdateRequestor = 42 {
+ enum OTAAnnouncementReason : ENUM8 {
+ kSimpleAnnouncement = 0;
+ kUpdateAvailable = 1;
+ kUrgentUpdateAvailable = 2;
+ }
+
+ enum OTAChangeReasonEnum : ENUM8 {
+ kUnknown = 0;
+ kSuccess = 1;
+ kFailure = 2;
+ kTimeOut = 3;
+ kDelayByProvider = 4;
+ }
+
+ enum OTAUpdateStateEnum : ENUM8 {
+ kUnknown = 0;
+ kIdle = 1;
+ kQuerying = 2;
+ kDelayedOnQuery = 3;
+ kDownloading = 4;
+ kApplying = 5;
+ kDelayedOnApply = 6;
+ kRollingBack = 7;
+ kDelayedOnUserConsent = 8;
+ }
+
+ fabric_scoped struct ProviderLocation {
+ node_id providerNodeID = 1;
+ endpoint_no endpoint = 2;
+ fabric_idx fabricIndex = 254;
+ }
+
+ info event StateTransition = 0 {
+ OTAUpdateStateEnum previousState = 0;
+ OTAUpdateStateEnum newState = 1;
+ OTAChangeReasonEnum reason = 2;
+ nullable INT32U targetSoftwareVersion = 3;
+ }
+
+ critical event VersionApplied = 1 {
+ INT32U softwareVersion = 0;
+ INT16U productID = 1;
+ }
+
+ info event DownloadError = 2 {
+ INT32U softwareVersion = 0;
+ INT64U bytesDownloaded = 1;
+ nullable INT8U progressPercent = 2;
+ nullable INT64S platformCode = 3;
+ }
+
+ attribute ProviderLocation defaultOTAProviders[] = 0;
+ readonly attribute boolean updatePossible = 1;
+ readonly attribute OTAUpdateStateEnum updateState = 2;
+ readonly attribute nullable int8u updateStateProgress = 3;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct AnnounceOTAProviderRequest {
+ node_id providerNodeID = 0;
+ vendor_id vendorID = 1;
+ OTAAnnouncementReason announcementReason = 2;
+ optional OCTET_STRING<512> metadataForNode = 3;
+ endpoint_no endpoint = 4;
+ }
+
+ command AnnounceOTAProvider(AnnounceOTAProviderRequest): DefaultSuccess = 0;
+}
+
+server cluster LocalizationConfiguration = 43 {
+ attribute char_string<35> activeLocale = 0;
+ readonly attribute CHAR_STRING supportedLocales[] = 1;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+}
+
+server cluster TimeFormatLocalization = 44 {
+ enum CalendarTypeEnum : ENUM8 {
+ kBuddhist = 0;
+ kChinese = 1;
+ kCoptic = 2;
+ kEthiopian = 3;
+ kGregorian = 4;
+ kHebrew = 5;
+ kIndian = 6;
+ kIslamic = 7;
+ kJapanese = 8;
+ kKorean = 9;
+ kPersian = 10;
+ kTaiwanese = 11;
+ }
+
+ enum HourFormatEnum : ENUM8 {
+ k12hr = 0;
+ k24hr = 1;
+ }
+
+ attribute HourFormatEnum hourFormat = 0;
+ attribute CalendarTypeEnum activeCalendarType = 1;
+ readonly attribute CalendarTypeEnum supportedCalendarTypes[] = 2;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+}
+
+server cluster GeneralCommissioning = 48 {
+ enum CommissioningError : ENUM8 {
+ kOk = 0;
+ kValueOutsideRange = 1;
+ kInvalidAuthentication = 2;
+ kNoFailSafe = 3;
+ kBusyWithOtherAdmin = 4;
+ }
+
+ enum RegulatoryLocationType : ENUM8 {
+ kIndoor = 0;
+ kOutdoor = 1;
+ kIndoorOutdoor = 2;
+ }
+
+ struct BasicCommissioningInfo {
+ int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
+ }
+
+ attribute access(write: administer) int64u breadcrumb = 0;
+ readonly attribute BasicCommissioningInfo basicCommissioningInfo = 1;
+ readonly attribute RegulatoryLocationType regulatoryConfig = 2;
+ readonly attribute RegulatoryLocationType locationCapability = 3;
+ readonly attribute boolean supportsConcurrentConnection = 4;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct ArmFailSafeRequest {
+ INT16U expiryLengthSeconds = 0;
+ INT64U breadcrumb = 1;
+ }
+
+ request struct SetRegulatoryConfigRequest {
+ RegulatoryLocationType newRegulatoryConfig = 0;
+ CHAR_STRING countryCode = 1;
+ INT64U breadcrumb = 2;
+ }
+
+ response struct ArmFailSafeResponse = 1 {
+ CommissioningError errorCode = 0;
+ CHAR_STRING debugText = 1;
+ }
+
+ response struct SetRegulatoryConfigResponse = 3 {
+ CommissioningError errorCode = 0;
+ CHAR_STRING debugText = 1;
+ }
+
+ response struct CommissioningCompleteResponse = 5 {
+ CommissioningError errorCode = 0;
+ CHAR_STRING debugText = 1;
+ }
+
+ command access(invoke: administer) ArmFailSafe(ArmFailSafeRequest): ArmFailSafeResponse = 0;
+ command access(invoke: administer) SetRegulatoryConfig(SetRegulatoryConfigRequest): SetRegulatoryConfigResponse = 2;
+ fabric command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4;
+}
+
+server cluster NetworkCommissioning = 49 {
+ enum NetworkCommissioningStatus : ENUM8 {
+ kSuccess = 0;
+ kOutOfRange = 1;
+ kBoundsExceeded = 2;
+ kNetworkIDNotFound = 3;
+ kDuplicateNetworkID = 4;
+ kNetworkNotFound = 5;
+ kRegulatoryError = 6;
+ kAuthFailure = 7;
+ kUnsupportedSecurity = 8;
+ kOtherConnectionFailure = 9;
+ kIPV6Failed = 10;
+ kIPBindFailed = 11;
+ kUnknownError = 12;
+ }
+
+ enum WiFiBand : ENUM8 {
+ k2g4 = 0;
+ k3g65 = 1;
+ k5g = 2;
+ k6g = 3;
+ k60g = 4;
+ }
+
+ bitmap NetworkCommissioningFeature : BITMAP32 {
+ kWiFiNetworkInterface = 0x1;
+ kThreadNetworkInterface = 0x2;
+ kEthernetNetworkInterface = 0x4;
+ }
+
+ bitmap WiFiSecurity : BITMAP8 {
+ kUnencrypted = 0x1;
+ kWep = 0x2;
+ kWpaPersonal = 0x4;
+ kWpa2Personal = 0x8;
+ kWpa3Personal = 0x10;
+ }
+
+ struct NetworkInfo {
+ octet_string<32> networkID = 0;
+ boolean connected = 1;
+ }
+
+ struct WiFiInterfaceScanResult {
+ WiFiSecurity security = 0;
+ octet_string<32> ssid = 1;
+ octet_string<6> bssid = 2;
+ int16u channel = 3;
+ WiFiBand wiFiBand = 4;
+ int8s rssi = 5;
+ }
+
+ struct ThreadInterfaceScanResult {
+ int16u panId = 0;
+ int64u extendedPanId = 1;
+ char_string<16> networkName = 2;
+ int16u channel = 3;
+ int8u version = 4;
+ octet_string<8> extendedAddress = 5;
+ int8s rssi = 6;
+ int8u lqi = 7;
+ }
+
+ readonly attribute access(read: administer) int8u maxNetworks = 0;
+ readonly attribute access(read: administer) NetworkInfo networks[] = 1;
+ readonly attribute int8u scanMaxTimeSeconds = 2;
+ readonly attribute int8u connectMaxTimeSeconds = 3;
+ attribute access(write: administer) boolean interfaceEnabled = 4;
+ readonly attribute access(read: administer) nullable NetworkCommissioningStatus lastNetworkingStatus = 5;
+ readonly attribute access(read: administer) nullable octet_string<32> lastNetworkID = 6;
+ readonly attribute access(read: administer) nullable int32s lastConnectErrorValue = 7;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct ScanNetworksRequest {
+ optional nullable OCTET_STRING<32> ssid = 0;
+ optional INT64U breadcrumb = 1;
+ }
+
+ request struct AddOrUpdateWiFiNetworkRequest {
+ OCTET_STRING<32> ssid = 0;
+ OCTET_STRING<64> credentials = 1;
+ optional INT64U breadcrumb = 2;
+ }
+
+ request struct AddOrUpdateThreadNetworkRequest {
+ OCTET_STRING<254> operationalDataset = 0;
+ optional INT64U breadcrumb = 1;
+ }
+
+ request struct RemoveNetworkRequest {
+ OCTET_STRING<32> networkID = 0;
+ optional INT64U breadcrumb = 1;
+ }
+
+ request struct ConnectNetworkRequest {
+ OCTET_STRING<32> networkID = 0;
+ optional INT64U breadcrumb = 1;
+ }
+
+ request struct ReorderNetworkRequest {
+ OCTET_STRING<32> networkID = 0;
+ INT8U networkIndex = 1;
+ optional INT64U breadcrumb = 2;
+ }
+
+ response struct ScanNetworksResponse = 1 {
+ NetworkCommissioningStatus networkingStatus = 0;
+ optional CHAR_STRING debugText = 1;
+ optional WiFiInterfaceScanResult wiFiScanResults[] = 2;
+ optional ThreadInterfaceScanResult threadScanResults[] = 3;
+ }
+
+ response struct NetworkConfigResponse = 5 {
+ NetworkCommissioningStatus networkingStatus = 0;
+ optional CHAR_STRING<512> debugText = 1;
+ optional INT8U networkIndex = 2;
+ }
+
+ response struct ConnectNetworkResponse = 7 {
+ NetworkCommissioningStatus networkingStatus = 0;
+ optional CHAR_STRING debugText = 1;
+ nullable INT32S errorValue = 2;
+ }
+
+ command access(invoke: administer) ScanNetworks(ScanNetworksRequest): ScanNetworksResponse = 0;
+ command access(invoke: administer) AddOrUpdateWiFiNetwork(AddOrUpdateWiFiNetworkRequest): NetworkConfigResponse = 2;
+ command access(invoke: administer) AddOrUpdateThreadNetwork(AddOrUpdateThreadNetworkRequest): NetworkConfigResponse = 3;
+ command access(invoke: administer) RemoveNetwork(RemoveNetworkRequest): NetworkConfigResponse = 4;
+ command access(invoke: administer) ConnectNetwork(ConnectNetworkRequest): ConnectNetworkResponse = 6;
+ command access(invoke: administer) ReorderNetwork(ReorderNetworkRequest): NetworkConfigResponse = 8;
+}
+
+server cluster DiagnosticLogs = 50 {
+ enum IntentEnum : ENUM8 {
+ kEndUserSupport = 0;
+ kNetworkDiag = 1;
+ kCrashLogs = 2;
+ }
+
+ enum StatusEnum : ENUM8 {
+ kSuccess = 0;
+ kExhausted = 1;
+ kNoLogs = 2;
+ kBusy = 3;
+ kDenied = 4;
+ }
+
+ enum TransferProtocolEnum : ENUM8 {
+ kResponsePayload = 0;
+ kBdx = 1;
+ }
+
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct RetrieveLogsRequestRequest {
+ IntentEnum intent = 0;
+ TransferProtocolEnum requestedProtocol = 1;
+ optional CHAR_STRING<32> transferFileDesignator = 2;
+ }
+
+ command RetrieveLogsRequest(RetrieveLogsRequestRequest): RetrieveLogsResponse = 0;
+}
+
+server cluster GeneralDiagnostics = 51 {
+ enum BootReasonEnum : ENUM8 {
+ kUnspecified = 0;
+ kPowerOnReboot = 1;
+ kBrownOutReset = 2;
+ kSoftwareWatchdogReset = 3;
+ kHardwareWatchdogReset = 4;
+ kSoftwareUpdateCompleted = 5;
+ kSoftwareReset = 6;
+ }
+
+ enum HardwareFaultEnum : ENUM8 {
+ kUnspecified = 0;
+ kRadio = 1;
+ kSensor = 2;
+ kResettableOverTemp = 3;
+ kNonResettableOverTemp = 4;
+ kPowerSource = 5;
+ kVisualDisplayFault = 6;
+ kAudioOutputFault = 7;
+ kUserInterfaceFault = 8;
+ kNonVolatileMemoryError = 9;
+ kTamperDetected = 10;
+ }
+
+ enum InterfaceTypeEnum : ENUM8 {
+ kUnspecified = 0;
+ kWiFi = 1;
+ kEthernet = 2;
+ kCellular = 3;
+ kThread = 4;
+ }
+
+ enum NetworkFaultEnum : ENUM8 {
+ kUnspecified = 0;
+ kHardwareFailure = 1;
+ kNetworkJammed = 2;
+ kConnectionFailed = 3;
+ }
+
+ enum RadioFaultEnum : ENUM8 {
+ kUnspecified = 0;
+ kWiFiFault = 1;
+ kCellularFault = 2;
+ kThreadFault = 3;
+ kNFCFault = 4;
+ kBLEFault = 5;
+ kEthernetFault = 6;
+ }
+
+ struct NetworkInterface {
+ char_string<32> name = 0;
+ boolean isOperational = 1;
+ nullable boolean offPremiseServicesReachableIPv4 = 2;
+ nullable boolean offPremiseServicesReachableIPv6 = 3;
+ octet_string<8> hardwareAddress = 4;
+ octet_string IPv4Addresses[] = 5;
+ octet_string IPv6Addresses[] = 6;
+ InterfaceTypeEnum type = 7;
+ }
+
+ critical event HardwareFaultChange = 0 {
+ HardwareFaultEnum current[] = 0;
+ HardwareFaultEnum previous[] = 1;
+ }
+
+ critical event RadioFaultChange = 1 {
+ RadioFaultEnum current[] = 0;
+ RadioFaultEnum previous[] = 1;
+ }
+
+ critical event NetworkFaultChange = 2 {
+ NetworkFaultEnum current[] = 0;
+ NetworkFaultEnum previous[] = 1;
+ }
+
+ critical event BootReason = 3 {
+ BootReasonEnum bootReason = 0;
+ }
+
+ readonly attribute NetworkInterface networkInterfaces[] = 0;
+ readonly attribute int16u rebootCount = 1;
+ readonly attribute int64u upTime = 2;
+ readonly attribute int32u totalOperationalHours = 3;
+ readonly attribute BootReasonEnum bootReason = 4;
+ readonly attribute HardwareFaultEnum activeHardwareFaults[] = 5;
+ readonly attribute RadioFaultEnum activeRadioFaults[] = 6;
+ readonly attribute NetworkFaultEnum activeNetworkFaults[] = 7;
+ readonly attribute boolean testEventTriggersEnabled = 8;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct TestEventTriggerRequest {
+ OCTET_STRING<16> enableKey = 0;
+ INT64U eventTrigger = 1;
+ }
+
+ command access(invoke: manage) TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0;
+}
+
+server cluster SoftwareDiagnostics = 52 {
+ bitmap SoftwareDiagnosticsFeature : BITMAP32 {
+ kWaterMarks = 0x1;
+ }
+
+ struct ThreadMetricsStruct {
+ int64u id = 0;
+ optional char_string<8> name = 1;
+ optional int32u stackFreeCurrent = 2;
+ optional int32u stackFreeMinimum = 3;
+ optional int32u stackSize = 4;
+ }
+
+ info event SoftwareFault = 0 {
+ INT64U id = 0;
+ optional CHAR_STRING name = 1;
+ optional OCTET_STRING faultRecording = 2;
+ }
+
+ readonly attribute ThreadMetricsStruct threadMetrics[] = 0;
+ readonly attribute int64u currentHeapFree = 1;
+ readonly attribute int64u currentHeapUsed = 2;
+ readonly attribute int64u currentHeapHighWatermark = 3;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ command ResetWatermarks(): DefaultSuccess = 0;
+}
+
+server cluster WiFiNetworkDiagnostics = 54 {
+ enum AssociationFailureCauseEnum : ENUM8 {
+ kUnknown = 0;
+ kAssociationFailed = 1;
+ kAuthenticationFailed = 2;
+ kSsidNotFound = 3;
+ }
+
+ enum ConnectionStatusEnum : ENUM8 {
+ kConnected = 0;
+ kNotConnected = 1;
+ }
+
+ enum SecurityTypeEnum : ENUM8 {
+ kUnspecified = 0;
+ kNone = 1;
+ kWep = 2;
+ kWpa = 3;
+ kWpa2 = 4;
+ kWpa3 = 5;
+ }
+
+ enum WiFiVersionEnum : ENUM8 {
+ kA = 0;
+ kB = 1;
+ kG = 2;
+ kN = 3;
+ kAc = 4;
+ kAx = 5;
+ }
+
+ bitmap WiFiNetworkDiagnosticsFeature : BITMAP32 {
+ kPacketCounts = 0x1;
+ kErrorCounts = 0x2;
+ }
+
+ info event Disconnection = 0 {
+ INT16U reasonCode = 0;
+ }
+
+ info event AssociationFailure = 1 {
+ AssociationFailureCauseEnum associationFailure = 0;
+ INT16U status = 1;
+ }
+
+ info event ConnectionStatus = 2 {
+ ConnectionStatusEnum connectionStatus = 0;
+ }
+
+ readonly attribute nullable octet_string<6> bssid = 0;
+ readonly attribute nullable SecurityTypeEnum securityType = 1;
+ readonly attribute nullable WiFiVersionEnum wiFiVersion = 2;
+ readonly attribute nullable int16u channelNumber = 3;
+ readonly attribute nullable int8s rssi = 4;
+ readonly attribute nullable int32u beaconLostCount = 5;
+ readonly attribute nullable int32u beaconRxCount = 6;
+ readonly attribute nullable int32u packetMulticastRxCount = 7;
+ readonly attribute nullable int32u packetMulticastTxCount = 8;
+ readonly attribute nullable int32u packetUnicastRxCount = 9;
+ readonly attribute nullable int32u packetUnicastTxCount = 10;
+ readonly attribute nullable int64u currentMaxRate = 11;
+ readonly attribute nullable int64u overrunCount = 12;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ command ResetCounts(): DefaultSuccess = 0;
+}
+
+server cluster AdministratorCommissioning = 60 {
+ enum CommissioningWindowStatusEnum : ENUM8 {
+ kWindowNotOpen = 0;
+ kEnhancedWindowOpen = 1;
+ kBasicWindowOpen = 2;
+ }
+
+ enum StatusCode : ENUM8 {
+ kBusy = 2;
+ kPAKEParameterError = 3;
+ kWindowNotOpen = 4;
+ }
+
+ readonly attribute CommissioningWindowStatusEnum windowStatus = 0;
+ readonly attribute nullable fabric_idx adminFabricIndex = 1;
+ readonly attribute nullable int16u adminVendorId = 2;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct OpenCommissioningWindowRequest {
+ INT16U commissioningTimeout = 0;
+ OCTET_STRING PAKEPasscodeVerifier = 1;
+ INT16U discriminator = 2;
+ INT32U iterations = 3;
+ OCTET_STRING salt = 4;
+ }
+
+ request struct OpenBasicCommissioningWindowRequest {
+ INT16U commissioningTimeout = 0;
+ }
+
+ timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0;
+ timed command access(invoke: administer) OpenBasicCommissioningWindow(OpenBasicCommissioningWindowRequest): DefaultSuccess = 1;
+ timed command access(invoke: administer) RevokeCommissioning(): DefaultSuccess = 2;
+}
+
+server cluster OperationalCredentials = 62 {
+ enum CertificateChainTypeEnum : ENUM8 {
+ kDACCertificate = 1;
+ kPAICertificate = 2;
+ }
+
+ enum NodeOperationalCertStatusEnum : ENUM8 {
+ kOk = 0;
+ kInvalidPublicKey = 1;
+ kInvalidNodeOpId = 2;
+ kInvalidNOC = 3;
+ kMissingCsr = 4;
+ kTableFull = 5;
+ kInvalidAdminSubject = 6;
+ kFabricConflict = 9;
+ kLabelConflict = 10;
+ kInvalidFabricIndex = 11;
+ }
+
+ fabric_scoped struct NOCStruct {
+ fabric_sensitive octet_string noc = 1;
+ nullable fabric_sensitive octet_string icac = 2;
+ fabric_idx fabricIndex = 254;
+ }
+
+ fabric_scoped struct FabricDescriptorStruct {
+ octet_string<65> rootPublicKey = 1;
+ vendor_id vendorID = 2;
+ fabric_id fabricID = 3;
+ node_id nodeID = 4;
+ char_string<32> label = 5;
+ fabric_idx fabricIndex = 254;
+ }
+
+ readonly attribute access(read: administer) NOCStruct NOCs[] = 0;
+ readonly attribute FabricDescriptorStruct fabrics[] = 1;
+ readonly attribute int8u supportedFabrics = 2;
+ readonly attribute int8u commissionedFabrics = 3;
+ readonly attribute OCTET_STRING trustedRootCertificates[] = 4;
+ readonly attribute int8u currentFabricIndex = 5;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct AttestationRequestRequest {
+ OCTET_STRING attestationNonce = 0;
+ }
+
+ request struct CertificateChainRequestRequest {
+ CertificateChainTypeEnum certificateType = 0;
+ }
+
+ request struct CSRRequestRequest {
+ OCTET_STRING CSRNonce = 0;
+ optional boolean isForUpdateNOC = 1;
+ }
+
+ request struct AddNOCRequest {
+ OCTET_STRING NOCValue = 0;
+ optional OCTET_STRING ICACValue = 1;
+ OCTET_STRING IPKValue = 2;
+ Int64u caseAdminSubject = 3;
+ VENDOR_ID adminVendorId = 4;
+ }
+
+ request struct UpdateNOCRequest {
+ OCTET_STRING NOCValue = 0;
+ optional OCTET_STRING ICACValue = 1;
+ }
+
+ request struct UpdateFabricLabelRequest {
+ CHAR_STRING<32> label = 0;
+ }
+
+ request struct RemoveFabricRequest {
+ fabric_idx fabricIndex = 0;
+ }
+
+ request struct AddTrustedRootCertificateRequest {
+ OCTET_STRING rootCACertificate = 0;
+ }
+
+ response struct AttestationResponse = 1 {
+ OCTET_STRING attestationElements = 0;
+ OCTET_STRING attestationSignature = 1;
+ }
+
+ response struct CertificateChainResponse = 3 {
+ OCTET_STRING certificate = 0;
+ }
+
+ response struct CSRResponse = 5 {
+ OCTET_STRING NOCSRElements = 0;
+ OCTET_STRING attestationSignature = 1;
+ }
+
+ response struct NOCResponse = 8 {
+ NodeOperationalCertStatusEnum statusCode = 0;
+ optional fabric_idx fabricIndex = 1;
+ optional CHAR_STRING debugText = 2;
+ }
+
+ command access(invoke: administer) AttestationRequest(AttestationRequestRequest): AttestationResponse = 0;
+ command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2;
+ command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4;
+ command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6;
+ fabric command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7;
+ fabric command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9;
+ command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10;
+ command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11;
+}
+
+server cluster GroupKeyManagement = 63 {
+ enum GroupKeySecurityPolicyEnum : ENUM8 {
+ kTrustFirst = 0;
+ kCacheAndSync = 1;
+ }
+
+ fabric_scoped struct GroupKeyMapStruct {
+ group_id groupId = 1;
+ int16u groupKeySetID = 2;
+ fabric_idx fabricIndex = 254;
+ }
+
+ fabric_scoped struct GroupInfoMapStruct {
+ group_id groupId = 1;
+ endpoint_no endpoints[] = 2;
+ optional char_string<16> groupName = 3;
+ fabric_idx fabricIndex = 254;
+ }
+
+ struct GroupKeySetStruct {
+ int16u groupKeySetID = 0;
+ GroupKeySecurityPolicyEnum groupKeySecurityPolicy = 1;
+ nullable octet_string<16> epochKey0 = 2;
+ nullable epoch_us epochStartTime0 = 3;
+ nullable octet_string<16> epochKey1 = 4;
+ nullable epoch_us epochStartTime1 = 5;
+ nullable octet_string<16> epochKey2 = 6;
+ nullable epoch_us epochStartTime2 = 7;
+ }
+
+ attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0;
+ readonly attribute GroupInfoMapStruct groupTable[] = 1;
+ readonly attribute int16u maxGroupsPerFabric = 2;
+ readonly attribute int16u maxGroupKeysPerFabric = 3;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct KeySetWriteRequest {
+ GroupKeySetStruct groupKeySet = 0;
+ }
+
+ request struct KeySetReadRequest {
+ INT16U groupKeySetID = 0;
+ }
+
+ request struct KeySetRemoveRequest {
+ INT16U groupKeySetID = 0;
+ }
+
+ request struct KeySetReadAllIndicesRequest {
+ INT16U groupKeySetIDs[] = 0;
+ }
+
+ response struct KeySetReadResponse = 2 {
+ GroupKeySetStruct groupKeySet = 0;
+ }
+
+ response struct KeySetReadAllIndicesResponse = 5 {
+ INT16U groupKeySetIDs[] = 0;
+ }
+
+ fabric command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0;
+ fabric command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1;
+ fabric command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3;
+ fabric command access(invoke: administer) KeySetReadAllIndices(KeySetReadAllIndicesRequest): KeySetReadAllIndicesResponse = 4;
+}
+
+server cluster FixedLabel = 64 {
+ readonly attribute LabelStruct labelList[] = 0;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+}
+
+server cluster UserLabel = 65 {
+ attribute access(write: manage) LabelStruct labelList[] = 0;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+}
+
+server cluster ColorControl = 768 {
+ enum ColorLoopAction : ENUM8 {
+ kDeactivate = 0;
+ kActivateFromColorLoopStartEnhancedHue = 1;
+ kActivateFromEnhancedCurrentHue = 2;
+ }
+
+ enum ColorLoopDirection : ENUM8 {
+ kDecrementHue = 0;
+ kIncrementHue = 1;
+ }
+
+ enum ColorMode : ENUM8 {
+ kCurrentHueAndCurrentSaturation = 0;
+ kCurrentXAndCurrentY = 1;
+ kColorTemperature = 2;
+ }
+
+ enum HueDirection : ENUM8 {
+ kShortestDistance = 0;
+ kLongestDistance = 1;
+ kUp = 2;
+ kDown = 3;
+ }
+
+ enum HueMoveMode : ENUM8 {
+ kStop = 0;
+ kUp = 1;
+ kDown = 3;
+ }
+
+ enum HueStepMode : ENUM8 {
+ kUp = 1;
+ kDown = 3;
+ }
+
+ enum SaturationMoveMode : ENUM8 {
+ kStop = 0;
+ kUp = 1;
+ kDown = 3;
+ }
+
+ enum SaturationStepMode : ENUM8 {
+ kUp = 1;
+ kDown = 3;
+ }
+
+ bitmap ColorCapabilities : BITMAP16 {
+ kHueSaturationSupported = 0x1;
+ kEnhancedHueSupported = 0x2;
+ kColorLoopSupported = 0x4;
+ kXYAttributesSupported = 0x8;
+ kColorTemperatureSupported = 0x10;
+ }
+
+ bitmap ColorControlFeature : BITMAP32 {
+ kHueAndSaturation = 0x1;
+ kEnhancedHue = 0x2;
+ kColorLoop = 0x4;
+ kXy = 0x8;
+ kColorTemperature = 0x10;
+ }
+
+ bitmap ColorLoopUpdateFlags : BITMAP8 {
+ kUpdateAction = 0x1;
+ kUpdateDirection = 0x2;
+ kUpdateTime = 0x4;
+ kUpdateStartHue = 0x8;
+ }
+
+ readonly attribute int8u currentHue = 0;
+ readonly attribute int8u currentSaturation = 1;
+ readonly attribute int16u remainingTime = 2;
+ readonly attribute int16u currentX = 3;
+ readonly attribute int16u currentY = 4;
+ readonly attribute int16u colorTemperatureMireds = 7;
+ readonly attribute enum8 colorMode = 8;
+ attribute bitmap8 options = 15;
+ readonly attribute nullable int8u numberOfPrimaries = 16;
+ readonly attribute int16u enhancedCurrentHue = 16384;
+ readonly attribute enum8 enhancedColorMode = 16385;
+ readonly attribute int8u colorLoopActive = 16386;
+ readonly attribute int8u colorLoopDirection = 16387;
+ readonly attribute int16u colorLoopTime = 16388;
+ readonly attribute int16u colorLoopStartEnhancedHue = 16389;
+ readonly attribute int16u colorLoopStoredEnhancedHue = 16390;
+ readonly attribute bitmap16 colorCapabilities = 16394;
+ readonly attribute int16u colorTempPhysicalMinMireds = 16395;
+ readonly attribute int16u colorTempPhysicalMaxMireds = 16396;
+ readonly attribute int16u coupleColorTempToLevelMinMireds = 16397;
+ attribute access(write: manage) nullable int16u startUpColorTemperatureMireds = 16400;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct MoveToHueRequest {
+ INT8U hue = 0;
+ HueDirection direction = 1;
+ INT16U transitionTime = 2;
+ BITMAP8 optionsMask = 3;
+ BITMAP8 optionsOverride = 4;
+ }
+
+ request struct MoveHueRequest {
+ HueMoveMode moveMode = 0;
+ INT8U rate = 1;
+ BITMAP8 optionsMask = 2;
+ BITMAP8 optionsOverride = 3;
+ }
+
+ request struct StepHueRequest {
+ HueStepMode stepMode = 0;
+ INT8U stepSize = 1;
+ INT8U transitionTime = 2;
+ BITMAP8 optionsMask = 3;
+ BITMAP8 optionsOverride = 4;
+ }
+
+ request struct MoveToSaturationRequest {
+ INT8U saturation = 0;
+ INT16U transitionTime = 1;
+ BITMAP8 optionsMask = 2;
+ BITMAP8 optionsOverride = 3;
+ }
+
+ request struct MoveSaturationRequest {
+ SaturationMoveMode moveMode = 0;
+ INT8U rate = 1;
+ BITMAP8 optionsMask = 2;
+ BITMAP8 optionsOverride = 3;
+ }
+
+ request struct StepSaturationRequest {
+ SaturationStepMode stepMode = 0;
+ INT8U stepSize = 1;
+ INT8U transitionTime = 2;
+ BITMAP8 optionsMask = 3;
+ BITMAP8 optionsOverride = 4;
+ }
+
+ request struct MoveToHueAndSaturationRequest {
+ INT8U hue = 0;
+ INT8U saturation = 1;
+ INT16U transitionTime = 2;
+ BITMAP8 optionsMask = 3;
+ BITMAP8 optionsOverride = 4;
+ }
+
+ request struct MoveToColorRequest {
+ INT16U colorX = 0;
+ INT16U colorY = 1;
+ INT16U transitionTime = 2;
+ BITMAP8 optionsMask = 3;
+ BITMAP8 optionsOverride = 4;
+ }
+
+ request struct MoveColorRequest {
+ INT16S rateX = 0;
+ INT16S rateY = 1;
+ BITMAP8 optionsMask = 2;
+ BITMAP8 optionsOverride = 3;
+ }
+
+ request struct StepColorRequest {
+ INT16S stepX = 0;
+ INT16S stepY = 1;
+ INT16U transitionTime = 2;
+ BITMAP8 optionsMask = 3;
+ BITMAP8 optionsOverride = 4;
+ }
+
+ request struct MoveToColorTemperatureRequest {
+ INT16U colorTemperatureMireds = 0;
+ INT16U transitionTime = 1;
+ BITMAP8 optionsMask = 2;
+ BITMAP8 optionsOverride = 3;
+ }
+
+ request struct EnhancedMoveToHueRequest {
+ INT16U enhancedHue = 0;
+ HueDirection direction = 1;
+ INT16U transitionTime = 2;
+ BITMAP8 optionsMask = 3;
+ BITMAP8 optionsOverride = 4;
+ }
+
+ request struct EnhancedMoveHueRequest {
+ HueMoveMode moveMode = 0;
+ INT16U rate = 1;
+ BITMAP8 optionsMask = 2;
+ BITMAP8 optionsOverride = 3;
+ }
+
+ request struct EnhancedStepHueRequest {
+ HueStepMode stepMode = 0;
+ INT16U stepSize = 1;
+ INT16U transitionTime = 2;
+ BITMAP8 optionsMask = 3;
+ BITMAP8 optionsOverride = 4;
+ }
+
+ request struct EnhancedMoveToHueAndSaturationRequest {
+ INT16U enhancedHue = 0;
+ INT8U saturation = 1;
+ INT16U transitionTime = 2;
+ BITMAP8 optionsMask = 3;
+ BITMAP8 optionsOverride = 4;
+ }
+
+ request struct ColorLoopSetRequest {
+ ColorLoopUpdateFlags updateFlags = 0;
+ ColorLoopAction action = 1;
+ ColorLoopDirection direction = 2;
+ INT16U time = 3;
+ INT16U startHue = 4;
+ BITMAP8 optionsMask = 5;
+ BITMAP8 optionsOverride = 6;
+ }
+
+ request struct StopMoveStepRequest {
+ BITMAP8 optionsMask = 0;
+ BITMAP8 optionsOverride = 1;
+ }
+
+ request struct MoveColorTemperatureRequest {
+ HueMoveMode moveMode = 0;
+ INT16U rate = 1;
+ INT16U colorTemperatureMinimumMireds = 2;
+ INT16U colorTemperatureMaximumMireds = 3;
+ BITMAP8 optionsMask = 4;
+ BITMAP8 optionsOverride = 5;
+ }
+
+ request struct StepColorTemperatureRequest {
+ HueStepMode stepMode = 0;
+ INT16U stepSize = 1;
+ INT16U transitionTime = 2;
+ INT16U colorTemperatureMinimumMireds = 3;
+ INT16U colorTemperatureMaximumMireds = 4;
+ BITMAP8 optionsMask = 5;
+ BITMAP8 optionsOverride = 6;
+ }
+
+ command MoveToHue(MoveToHueRequest): DefaultSuccess = 0;
+ command MoveHue(MoveHueRequest): DefaultSuccess = 1;
+ command StepHue(StepHueRequest): DefaultSuccess = 2;
+ command MoveToSaturation(MoveToSaturationRequest): DefaultSuccess = 3;
+ command MoveSaturation(MoveSaturationRequest): DefaultSuccess = 4;
+ command StepSaturation(StepSaturationRequest): DefaultSuccess = 5;
+ command MoveToHueAndSaturation(MoveToHueAndSaturationRequest): DefaultSuccess = 6;
+ command MoveToColor(MoveToColorRequest): DefaultSuccess = 7;
+ command MoveColor(MoveColorRequest): DefaultSuccess = 8;
+ command StepColor(StepColorRequest): DefaultSuccess = 9;
+ command MoveToColorTemperature(MoveToColorTemperatureRequest): DefaultSuccess = 10;
+ command EnhancedMoveToHue(EnhancedMoveToHueRequest): DefaultSuccess = 64;
+ command EnhancedMoveHue(EnhancedMoveHueRequest): DefaultSuccess = 65;
+ command EnhancedStepHue(EnhancedStepHueRequest): DefaultSuccess = 66;
+ command EnhancedMoveToHueAndSaturation(EnhancedMoveToHueAndSaturationRequest): DefaultSuccess = 67;
+ command ColorLoopSet(ColorLoopSetRequest): DefaultSuccess = 68;
+ command StopMoveStep(StopMoveStepRequest): DefaultSuccess = 71;
+ command MoveColorTemperature(MoveColorTemperatureRequest): DefaultSuccess = 75;
+ command StepColorTemperature(StepColorTemperatureRequest): DefaultSuccess = 76;
+}
+
+endpoint 0 {
+ device type rootdevice = 22, version 1;
+ binding cluster OtaSoftwareUpdateProvider;
+
+ server cluster Groups {
+ ram attribute nameSupport;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 4;
+ }
+
+ server cluster Descriptor {
+ callback attribute deviceTypeList;
+ callback attribute serverList;
+ callback attribute clientList;
+ callback attribute partsList;
+ ram attribute featureMap;
+ callback attribute clusterRevision default = 1;
+ }
+
+ server cluster AccessControl {
+ callback attribute acl;
+ callback attribute extension;
+ callback attribute subjectsPerAccessControlEntry default = 4;
+ callback attribute targetsPerAccessControlEntry default = 3;
+ callback attribute accessControlEntriesPerFabric default = 4;
+ callback attribute attributeList;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster BasicInformation {
+ 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;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster OtaSoftwareUpdateRequestor {
+ callback attribute defaultOTAProviders;
+ ram attribute updatePossible default = 1;
+ ram attribute updateState;
+ ram attribute updateStateProgress;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster LocalizationConfiguration {
+ persist attribute activeLocale default = "en-US";
+ callback attribute supportedLocales;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster TimeFormatLocalization {
+ persist attribute hourFormat;
+ persist attribute activeCalendarType;
+ callback attribute supportedCalendarTypes;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster GeneralCommissioning {
+ ram attribute breadcrumb;
+ callback attribute basicCommissioningInfo;
+ callback attribute regulatoryConfig;
+ callback attribute locationCapability;
+ callback attribute supportsConcurrentConnection default = 1;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster NetworkCommissioning {
+ ram attribute maxNetworks;
+ callback attribute networks;
+ ram attribute scanMaxTimeSeconds;
+ ram attribute connectMaxTimeSeconds;
+ ram attribute interfaceEnabled;
+ ram attribute lastNetworkingStatus;
+ ram attribute lastNetworkID;
+ ram attribute lastConnectErrorValue;
+ ram attribute featureMap default = 2;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster DiagnosticLogs {
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster GeneralDiagnostics {
+ callback attribute networkInterfaces;
+ callback attribute rebootCount;
+ callback attribute upTime;
+ callback attribute totalOperationalHours;
+ callback attribute bootReason;
+ callback attribute activeHardwareFaults;
+ callback attribute activeRadioFaults;
+ callback attribute activeNetworkFaults;
+ callback attribute testEventTriggersEnabled;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster SoftwareDiagnostics {
+ callback attribute threadMetrics;
+ callback attribute currentHeapFree;
+ callback attribute currentHeapUsed;
+ callback attribute currentHeapHighWatermark;
+ ram attribute featureMap default = 1;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster WiFiNetworkDiagnostics {
+ callback attribute bssid;
+ callback attribute securityType;
+ callback attribute wiFiVersion;
+ callback attribute channelNumber;
+ callback attribute rssi;
+ callback attribute beaconLostCount;
+ callback attribute beaconRxCount;
+ callback attribute packetMulticastRxCount;
+ callback attribute packetMulticastTxCount;
+ callback attribute packetUnicastRxCount;
+ callback attribute packetUnicastTxCount;
+ callback attribute currentMaxRate;
+ callback attribute overrunCount;
+ ram attribute featureMap default = 3;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster AdministratorCommissioning {
+ callback attribute windowStatus;
+ callback attribute adminFabricIndex default = 1;
+ callback attribute adminVendorId;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster OperationalCredentials {
+ callback attribute NOCs;
+ callback attribute fabrics;
+ callback attribute supportedFabrics;
+ callback attribute commissionedFabrics;
+ callback attribute trustedRootCertificates;
+ callback attribute currentFabricIndex;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster GroupKeyManagement {
+ callback attribute groupKeyMap;
+ callback attribute groupTable;
+ callback attribute maxGroupsPerFabric;
+ callback attribute maxGroupKeysPerFabric;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster FixedLabel {
+ callback attribute labelList;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+
+ server cluster UserLabel {
+ callback attribute labelList;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 1;
+ }
+}
+endpoint 1 {
+ device type dimmablelight = 257, version 1;
+
+ server cluster Identify {
+ ram attribute identifyTime;
+ ram attribute identifyType;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 4;
+ }
+
+ server cluster Groups {
+ ram attribute nameSupport;
+ ram attribute featureMap;
+ ram attribute clusterRevision default = 4;
+ }
+
+ server cluster OnOff {
+ persist attribute onOff;
+ ram attribute globalSceneControl default = 0x01;
+ ram attribute onTime;
+ ram attribute offWaitTime;
+ persist attribute startUpOnOff default = 0xFF;
+ ram attribute featureMap default = 1;
+ ram attribute clusterRevision default = 4;
+ }
+
+ server cluster LevelControl {
+ persist attribute currentLevel default = 0x01;
+ ram attribute remainingTime;
+ ram attribute minLevel default = 0x01;
+ ram attribute maxLevel default = 0xFE;
+ ram attribute currentFrequency;
+ ram attribute minFrequency;
+ ram attribute maxFrequency;
+ ram attribute options;
+ ram attribute onOffTransitionTime;
+ ram attribute onLevel default = 0xFF;
+ ram attribute onTransitionTime;
+ ram attribute offTransitionTime;
+ ram attribute defaultMoveRate default = 50;
+ persist attribute startUpCurrentLevel default = 255;
+ ram attribute featureMap default = 3;
+ ram attribute clusterRevision default = 5;
+ }
+
+ server cluster Descriptor {
+ callback attribute deviceTypeList;
+ callback attribute serverList;
+ callback attribute clientList;
+ callback attribute partsList;
+ ram attribute featureMap;
+ callback attribute clusterRevision default = 1;
+ }
+
+ server cluster ColorControl {
+ ram attribute currentHue;
+ ram attribute currentSaturation;
+ ram attribute remainingTime;
+ ram attribute currentX default = 0x616B;
+ ram attribute currentY default = 0x607D;
+ ram attribute colorTemperatureMireds default = 0x00FA;
+ ram attribute colorMode default = 0x01;
+ ram attribute options;
+ ram attribute numberOfPrimaries;
+ ram attribute enhancedCurrentHue;
+ ram attribute enhancedColorMode default = 0x01;
+ ram attribute colorLoopActive;
+ ram attribute colorLoopDirection;
+ ram attribute colorLoopTime default = 0x0019;
+ ram attribute colorLoopStartEnhancedHue default = 0x2300;
+ ram attribute colorLoopStoredEnhancedHue;
+ ram attribute colorCapabilities default = 0x1F;
+ ram attribute colorTempPhysicalMinMireds;
+ ram attribute colorTempPhysicalMaxMireds default = 0xFEFF;
+ ram attribute coupleColorTempToLevelMinMireds;
+ ram attribute startUpColorTemperatureMireds;
+ ram attribute featureMap default = 0x1F;
+ ram attribute clusterRevision default = 5;
+ }
+}
+
+
diff --git a/silabs_examples/Direct_Internet_lighting-app/data_model/lighting-wifi-app.zap b/silabs_examples/Direct_Internet_lighting-app/data_model/lighting-wifi-app.zap
new file mode 100644
index 00000000000000..a4319b63e815d2
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/data_model/lighting-wifi-app.zap
@@ -0,0 +1,8198 @@
+{
+ "featureLevel": 92,
+ "creator": "zap",
+ "keyValuePairs": [
+ {
+ "key": "commandDiscovery",
+ "value": "1"
+ },
+ {
+ "key": "defaultResponsePolicy",
+ "value": "always"
+ },
+ {
+ "key": "manufacturerCodes",
+ "value": "0x1002"
+ }
+ ],
+ "package": [
+ {
+ "pathRelativity": "relativeToZap",
+ "path": "../../../src/app/zap-templates/zcl/zcl.json",
+ "type": "zcl-properties",
+ "category": "matter",
+ "version": 1,
+ "description": "Matter SDK ZCL data"
+ },
+ {
+ "pathRelativity": "relativeToZap",
+ "path": "../../../../src/app/zap-templates/app-templates.json",
+ "type": "gen-templates-json",
+ "version": "chip-v1"
+ }
+ ],
+ "endpointTypes": [
+ {
+ "name": "MA-rootdevice",
+ "deviceTypeName": "MA-rootdevice",
+ "deviceTypeCode": 22,
+ "deviceTypeProfileId": 259,
+ "clusters": [
+ {
+ "name": "Identify",
+ "code": 3,
+ "mfgCode": null,
+ "define": "IDENTIFY_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "Identify",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Identify",
+ "code": 3,
+ "mfgCode": null,
+ "define": "IDENTIFY_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "IdentifyTime",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Groups",
+ "code": 4,
+ "mfgCode": null,
+ "define": "GROUPS_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "AddGroup",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "ViewGroup",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "GetGroupMembership",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RemoveGroup",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RemoveAllGroups",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "AddGroupIfIdentifying",
+ "code": 5,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Groups",
+ "code": 4,
+ "mfgCode": null,
+ "define": "GROUPS_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "commands": [
+ {
+ "name": "AddGroupResponse",
+ "code": 0,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "ViewGroupResponse",
+ "code": 1,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "GetGroupMembershipResponse",
+ "code": 2,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "RemoveGroupResponse",
+ "code": 3,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "NameSupport",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "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": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Scenes",
+ "code": 5,
+ "mfgCode": null,
+ "define": "SCENES_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "AddScene",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "ViewScene",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RemoveScene",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RemoveAllScenes",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "StoreScene",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RecallScene",
+ "code": 5,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "GetSceneMembership",
+ "code": 6,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Scenes",
+ "code": 5,
+ "mfgCode": null,
+ "define": "SCENES_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "AddSceneResponse",
+ "code": 0,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "ViewSceneResponse",
+ "code": 1,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "RemoveSceneResponse",
+ "code": 2,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "RemoveAllScenesResponse",
+ "code": 3,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "StoreSceneResponse",
+ "code": 4,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "GetSceneMembershipResponse",
+ "code": 6,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "SceneCount",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentScene",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentGroup",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "group_id",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "SceneValid",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "NameSupport",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "On/Off",
+ "code": 6,
+ "mfgCode": null,
+ "define": "ON_OFF_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "Off",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "On",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "Toggle",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "On/Off",
+ "code": 6,
+ "mfgCode": null,
+ "define": "ON_OFF_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "OnOff",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "On/off Switch Configuration",
+ "code": 7,
+ "mfgCode": null,
+ "define": "ON_OFF_SWITCH_CONFIGURATION_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "On/off Switch Configuration",
+ "code": 7,
+ "mfgCode": null,
+ "define": "ON_OFF_SWITCH_CONFIGURATION_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "switch type",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "enum8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "switch actions",
+ "code": 16,
+ "mfgCode": null,
+ "side": "server",
+ "type": "enum8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Level Control",
+ "code": 8,
+ "mfgCode": null,
+ "define": "LEVEL_CONTROL_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "MoveToLevel",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "Move",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "Step",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "Stop",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "MoveToLevelWithOnOff",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "MoveWithOnOff",
+ "code": 5,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "StepWithOnOff",
+ "code": 6,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "StopWithOnOff",
+ "code": 7,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "5",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Level Control",
+ "code": 8,
+ "mfgCode": null,
+ "define": "LEVEL_CONTROL_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "CurrentLevel",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "5",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Descriptor",
+ "code": 29,
+ "mfgCode": null,
+ "define": "DESCRIPTOR_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "attributes": [
+ {
+ "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": "Descriptor",
+ "code": 29,
+ "mfgCode": null,
+ "define": "DESCRIPTOR_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "DeviceTypeList",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ServerList",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClientList",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PartsList",
+ "code": 3,
+ "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": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Access Control",
+ "code": 31,
+ "mfgCode": null,
+ "define": "ACCESS_CONTROL_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "attributes": [
+ {
+ "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": "Access Control",
+ "code": 31,
+ "mfgCode": null,
+ "define": "ACCESS_CONTROL_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "ACL",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Extension",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "SubjectsPerAccessControlEntry",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "TargetsPerAccessControlEntry",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "3",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AccessControlEntriesPerFabric",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "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": "Basic Information",
+ "code": 40,
+ "mfgCode": null,
+ "define": "BASIC_INFORMATION_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Basic Information",
+ "code": 40,
+ "mfgCode": null,
+ "define": "BASIC_INFORMATION_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "DataModelRevision",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "10",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "VendorName",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "VendorID",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "vendor_id",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ProductName",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ProductID",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "NodeLabel",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "Location",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "XX",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "HardwareVersion",
+ "code": 7,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "HardwareVersionString",
+ "code": 8,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "SoftwareVersion",
+ "code": 9,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "SoftwareVersionString",
+ "code": 10,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ManufacturingDate",
+ "code": 11,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "20210614123456ZZ",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "PartNumber",
+ "code": 12,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ProductURL",
+ "code": 13,
+ "mfgCode": null,
+ "side": "server",
+ "type": "long_char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ProductLabel",
+ "code": 14,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "SerialNumber",
+ "code": 15,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "LocalConfigDisabled",
+ "code": 16,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "Reachable",
+ "code": 17,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "UniqueID",
+ "code": 18,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CapabilityMinima",
+ "code": 19,
+ "mfgCode": null,
+ "side": "server",
+ "type": "CapabilityMinimaStruct",
+ "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": 1,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "OTA Software Update Provider",
+ "code": 41,
+ "mfgCode": null,
+ "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER",
+ "side": "client",
+ "enabled": 1,
+ "commands": [
+ {
+ "name": "QueryImage",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "ApplyUpdateRequest",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "NotifyUpdateApplied",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 0,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "OTA Software Update Provider",
+ "code": 41,
+ "mfgCode": null,
+ "define": "OTA_SOFTWARE_UPDATE_PROVIDER_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "QueryImageResponse",
+ "code": 1,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "ApplyUpdateResponse",
+ "code": 3,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "AttributeList",
+ "code": 65531,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 0,
+ "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": 0,
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "OTA Software Update Requestor",
+ "code": 42,
+ "mfgCode": null,
+ "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "AnnounceOTAProvider",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "OTA Software Update Requestor",
+ "code": 42,
+ "mfgCode": null,
+ "define": "OTA_SOFTWARE_UPDATE_REQUESTOR_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "DefaultOTAProviders",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "UpdatePossible",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "UpdateState",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "OTAUpdateStateEnum",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "UpdateStateProgress",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AttributeList",
+ "code": 65531,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 0,
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Localization Configuration",
+ "code": 43,
+ "mfgCode": null,
+ "define": "LOCALIZATION_CONFIGURATION_CLUSTER",
+ "side": "client",
+ "enabled": 0
+ },
+ {
+ "name": "Localization Configuration",
+ "code": 43,
+ "mfgCode": null,
+ "define": "LOCALIZATION_CONFIGURATION_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "ActiveLocale",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "en-US",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "SupportedLocales",
+ "code": 1,
+ "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": "Time Format Localization",
+ "code": 44,
+ "mfgCode": null,
+ "define": "TIME_FORMAT_LOCALIZATION_CLUSTER",
+ "side": "client",
+ "enabled": 0
+ },
+ {
+ "name": "Time Format Localization",
+ "code": 44,
+ "mfgCode": null,
+ "define": "TIME_FORMAT_LOCALIZATION_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "HourFormat",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "HourFormatEnum",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ActiveCalendarType",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "CalendarTypeEnum",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "SupportedCalendarTypes",
+ "code": 2,
+ "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": "Unit Localization",
+ "code": 45,
+ "mfgCode": null,
+ "define": "UNIT_LOCALIZATION_CLUSTER",
+ "side": "client",
+ "enabled": 0
+ },
+ {
+ "name": "Unit Localization",
+ "code": 45,
+ "mfgCode": null,
+ "define": "UNIT_LOCALIZATION_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "TemperatureUnit",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "TempUnitEnum",
+ "included": 0,
+ "storageOption": "NVM",
+ "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": "General Commissioning",
+ "code": 48,
+ "mfgCode": null,
+ "define": "GENERAL_COMMISSIONING_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "ArmFailSafe",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "SetRegulatoryConfig",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "CommissioningComplete",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "General Commissioning",
+ "code": 48,
+ "mfgCode": null,
+ "define": "GENERAL_COMMISSIONING_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "commands": [
+ {
+ "name": "ArmFailSafeResponse",
+ "code": 1,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "SetRegulatoryConfigResponse",
+ "code": 3,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "CommissioningCompleteResponse",
+ "code": 5,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 1,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "Breadcrumb",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "BasicCommissioningInfo",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "BasicCommissioningInfo",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RegulatoryConfig",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "RegulatoryLocationType",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "LocationCapability",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "RegulatoryLocationType",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "SupportsConcurrentConnection",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Network Commissioning",
+ "code": 49,
+ "mfgCode": null,
+ "define": "NETWORK_COMMISSIONING_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "ScanNetworks",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "AddOrUpdateWiFiNetwork",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "AddOrUpdateThreadNetwork",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RemoveNetwork",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "ConnectNetwork",
+ "code": 6,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "ReorderNetwork",
+ "code": 8,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Network Commissioning",
+ "code": 49,
+ "mfgCode": null,
+ "define": "NETWORK_COMMISSIONING_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "commands": [
+ {
+ "name": "ScanNetworksResponse",
+ "code": 1,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "NetworkConfigResponse",
+ "code": 5,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "ConnectNetworkResponse",
+ "code": 7,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "MaxNetworks",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Networks",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ScanMaxTimeSeconds",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ConnectMaxTimeSeconds",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "InterfaceEnabled",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "LastNetworkingStatus",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "NetworkCommissioningStatus",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "LastNetworkID",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "octet_string",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "LastConnectErrorValue",
+ "code": 7,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32s",
+ "included": 1,
+ "storageOption": "RAM",
+ "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": "2",
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Diagnostic Logs",
+ "code": 50,
+ "mfgCode": null,
+ "define": "DIAGNOSTIC_LOGS_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "commands": [
+ {
+ "name": "RetrieveLogsRequest",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "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": "General Diagnostics",
+ "code": 51,
+ "mfgCode": null,
+ "define": "GENERAL_DIAGNOSTICS_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "General Diagnostics",
+ "code": 51,
+ "mfgCode": null,
+ "define": "GENERAL_DIAGNOSTICS_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "commands": [
+ {
+ "name": "TestEventTrigger",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "NetworkInterfaces",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RebootCount",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "UpTime",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "TotalOperationalHours",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "BootReason",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "BootReasonEnum",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ActiveHardwareFaults",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ActiveRadioFaults",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ActiveNetworkFaults",
+ "code": 7,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "TestEventTriggersEnabled",
+ "code": 8,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "false",
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Software Diagnostics",
+ "code": 52,
+ "mfgCode": null,
+ "define": "SOFTWARE_DIAGNOSTICS_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "ResetWatermarks",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Software Diagnostics",
+ "code": 52,
+ "mfgCode": null,
+ "define": "SOFTWARE_DIAGNOSTICS_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "ThreadMetrics",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentHeapFree",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentHeapUsed",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentHeapHighWatermark",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "FeatureMap",
+ "code": 65532,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap32",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Thread Network Diagnostics",
+ "code": 53,
+ "mfgCode": null,
+ "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "ResetCounts",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Thread Network Diagnostics",
+ "code": 53,
+ "mfgCode": null,
+ "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "Channel",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RoutingRole",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "RoutingRole",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "NetworkName",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "PanId",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ExtendedPanId",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "MeshLocalPrefix",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "octet_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "OverrunCount",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "NeighborTable",
+ "code": 7,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RouteTable",
+ "code": 8,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "PartitionId",
+ "code": 9,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "Weighting",
+ "code": 10,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "DataVersion",
+ "code": 11,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "StableDataVersion",
+ "code": 12,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "LeaderRouterId",
+ "code": 13,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "DetachedRoleCount",
+ "code": 14,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ChildRoleCount",
+ "code": 15,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RouterRoleCount",
+ "code": 16,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "LeaderRoleCount",
+ "code": 17,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "AttachAttemptCount",
+ "code": 18,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "PartitionIdChangeCount",
+ "code": 19,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "BetterPartitionAttachAttemptCount",
+ "code": 20,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ParentChangeCount",
+ "code": 21,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxTotalCount",
+ "code": 22,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxUnicastCount",
+ "code": 23,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxBroadcastCount",
+ "code": 24,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxAckRequestedCount",
+ "code": 25,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxAckedCount",
+ "code": 26,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxNoAckRequestedCount",
+ "code": 27,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxDataCount",
+ "code": 28,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxDataPollCount",
+ "code": 29,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxBeaconCount",
+ "code": 30,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxBeaconRequestCount",
+ "code": 31,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxOtherCount",
+ "code": 32,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxRetryCount",
+ "code": 33,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxDirectMaxRetryExpiryCount",
+ "code": 34,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxIndirectMaxRetryExpiryCount",
+ "code": 35,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxErrCcaCount",
+ "code": 36,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxErrAbortCount",
+ "code": 37,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxErrBusyChannelCount",
+ "code": 38,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxTotalCount",
+ "code": 39,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxUnicastCount",
+ "code": 40,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxBroadcastCount",
+ "code": 41,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxDataCount",
+ "code": 42,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxDataPollCount",
+ "code": 43,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxBeaconCount",
+ "code": 44,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxBeaconRequestCount",
+ "code": 45,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxOtherCount",
+ "code": 46,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxAddressFilteredCount",
+ "code": 47,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxDestAddrFilteredCount",
+ "code": 48,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxDuplicatedCount",
+ "code": 49,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxErrNoFrameCount",
+ "code": 50,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxErrUnknownNeighborCount",
+ "code": 51,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxErrInvalidSrcAddrCount",
+ "code": 52,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxErrSecCount",
+ "code": 53,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxErrFcsCount",
+ "code": 54,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RxErrOtherCount",
+ "code": 55,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ActiveTimestamp",
+ "code": 56,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PendingTimestamp",
+ "code": 57,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Delay",
+ "code": 58,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "SecurityPolicy",
+ "code": 59,
+ "mfgCode": null,
+ "side": "server",
+ "type": "SecurityPolicy",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ChannelPage0Mask",
+ "code": 60,
+ "mfgCode": null,
+ "side": "server",
+ "type": "octet_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "OperationalDatasetComponents",
+ "code": 61,
+ "mfgCode": null,
+ "side": "server",
+ "type": "OperationalDatasetComponents",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ActiveNetworkFaultsList",
+ "code": 62,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "FeatureMap",
+ "code": 65532,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap32",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x000F",
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "WiFi Network Diagnostics",
+ "code": 54,
+ "mfgCode": null,
+ "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "ResetCounts",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "WiFi Network Diagnostics",
+ "code": 54,
+ "mfgCode": null,
+ "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "BSSID",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "octet_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "SecurityType",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "SecurityTypeEnum",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "WiFiVersion",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "WiFiVersionEnum",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ChannelNumber",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RSSI",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8s",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "BeaconLostCount",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "BeaconRxCount",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PacketMulticastRxCount",
+ "code": 7,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PacketMulticastTxCount",
+ "code": 8,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PacketUnicastRxCount",
+ "code": 9,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PacketUnicastTxCount",
+ "code": 10,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentMaxRate",
+ "code": 11,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "OverrunCount",
+ "code": 12,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "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": "3",
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Ethernet Network Diagnostics",
+ "code": 55,
+ "mfgCode": null,
+ "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "ResetCounts",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Ethernet Network Diagnostics",
+ "code": 55,
+ "mfgCode": null,
+ "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "PHYRate",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "PHYRateEnum",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "FullDuplex",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PacketRxCount",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "PacketTxCount",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TxErrCount",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CollisionCount",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "OverrunCount",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CarrierDetect",
+ "code": 7,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "TimeSinceReset",
+ "code": 8,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000000000000000",
+ "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": "3",
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Switch",
+ "code": 59,
+ "mfgCode": null,
+ "define": "SWITCH_CLUSTER",
+ "side": "client",
+ "enabled": 0
+ },
+ {
+ "name": "Switch",
+ "code": 59,
+ "mfgCode": null,
+ "define": "SWITCH_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "attributes": [
+ {
+ "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": "Administrator Commissioning",
+ "code": 60,
+ "mfgCode": null,
+ "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "OpenCommissioningWindow",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "OpenBasicCommissioningWindow",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "RevokeCommissioning",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Administrator Commissioning",
+ "code": 60,
+ "mfgCode": null,
+ "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "WindowStatus",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "CommissioningWindowStatusEnum",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AdminFabricIndex",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "fabric_idx",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AdminVendorId",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Operational Credentials",
+ "code": 62,
+ "mfgCode": null,
+ "define": "OPERATIONAL_CREDENTIALS_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "AttestationRequest",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "CertificateChainRequest",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "CSRRequest",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "AddNOC",
+ "code": 6,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "UpdateNOC",
+ "code": 7,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "UpdateFabricLabel",
+ "code": 9,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "RemoveFabric",
+ "code": 10,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "AddTrustedRootCertificate",
+ "code": 11,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Operational Credentials",
+ "code": 62,
+ "mfgCode": null,
+ "define": "OPERATIONAL_CREDENTIALS_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "commands": [
+ {
+ "name": "AttestationResponse",
+ "code": 1,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "CertificateChainResponse",
+ "code": 3,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "CSRResponse",
+ "code": 5,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "NOCResponse",
+ "code": 8,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 1,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "NOCs",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Fabrics",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "SupportedFabrics",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CommissionedFabrics",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "TrustedRootCertificates",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentFabricIndex",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "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": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Group Key Management",
+ "code": 63,
+ "mfgCode": null,
+ "define": "GROUP_KEY_MANAGEMENT_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "KeySetWrite",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "KeySetRead",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "KeySetRemove",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "KeySetReadAllIndices",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ]
+ },
+ {
+ "name": "Group Key Management",
+ "code": 63,
+ "mfgCode": null,
+ "define": "GROUP_KEY_MANAGEMENT_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "commands": [
+ {
+ "name": "KeySetReadResponse",
+ "code": 2,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "KeySetReadAllIndicesResponse",
+ "code": 5,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "GroupKeyMap",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "GroupTable",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "MaxGroupsPerFabric",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "MaxGroupKeysPerFabric",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "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": "Fixed Label",
+ "code": 64,
+ "mfgCode": null,
+ "define": "FIXED_LABEL_CLUSTER",
+ "side": "client",
+ "enabled": 0
+ },
+ {
+ "name": "Fixed Label",
+ "code": 64,
+ "mfgCode": null,
+ "define": "FIXED_LABEL_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "LabelList",
+ "code": 0,
+ "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": "User Label",
+ "code": 65,
+ "mfgCode": null,
+ "define": "USER_LABEL_CLUSTER",
+ "side": "client",
+ "enabled": 0
+ },
+ {
+ "name": "User Label",
+ "code": 65,
+ "mfgCode": null,
+ "define": "USER_LABEL_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "LabelList",
+ "code": 0,
+ "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": "MA-dimmablelight",
+ "deviceTypeName": "MA-dimmablelight",
+ "deviceTypeCode": 257,
+ "deviceTypeProfileId": 259,
+ "clusters": [
+ {
+ "name": "Identify",
+ "code": 3,
+ "mfgCode": null,
+ "define": "IDENTIFY_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "Identify",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "TriggerEffect",
+ "code": 64,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Identify",
+ "code": 3,
+ "mfgCode": null,
+ "define": "IDENTIFY_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "IdentifyTime",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "IdentifyType",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "enum8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0",
+ "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": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Groups",
+ "code": 4,
+ "mfgCode": null,
+ "define": "GROUPS_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "AddGroup",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "ViewGroup",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "GetGroupMembership",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RemoveGroup",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RemoveAllGroups",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "AddGroupIfIdentifying",
+ "code": 5,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Groups",
+ "code": 4,
+ "mfgCode": null,
+ "define": "GROUPS_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "commands": [
+ {
+ "name": "AddGroupResponse",
+ "code": 0,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "ViewGroupResponse",
+ "code": 1,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "GetGroupMembershipResponse",
+ "code": 2,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "RemoveGroupResponse",
+ "code": 3,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "NameSupport",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "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": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Scenes",
+ "code": 5,
+ "mfgCode": null,
+ "define": "SCENES_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "AddScene",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "ViewScene",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RemoveScene",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RemoveAllScenes",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "StoreScene",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "RecallScene",
+ "code": 5,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "GetSceneMembership",
+ "code": 6,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "EnhancedAddScene",
+ "code": 64,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "EnhancedViewScene",
+ "code": 65,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "CopyScene",
+ "code": 66,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Scenes",
+ "code": 5,
+ "mfgCode": null,
+ "define": "SCENES_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "AddSceneResponse",
+ "code": 0,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "ViewSceneResponse",
+ "code": 1,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "RemoveSceneResponse",
+ "code": 2,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "RemoveAllScenesResponse",
+ "code": 3,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "StoreSceneResponse",
+ "code": 4,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ },
+ {
+ "name": "GetSceneMembershipResponse",
+ "code": 6,
+ "mfgCode": null,
+ "source": "server",
+ "incoming": 0,
+ "outgoing": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "SceneCount",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentScene",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentGroup",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "group_id",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "SceneValid",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "NameSupport",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "On/Off",
+ "code": 6,
+ "mfgCode": null,
+ "define": "ON_OFF_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "Off",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "On",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "Toggle",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "OffWithEffect",
+ "code": 64,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "OnWithRecallGlobalScene",
+ "code": 65,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "OnWithTimedOff",
+ "code": 66,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "On/Off",
+ "code": 6,
+ "mfgCode": null,
+ "define": "ON_OFF_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "OnOff",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "GlobalSceneControl",
+ "code": 16384,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x01",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "OnTime",
+ "code": 16385,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "OffWaitTime",
+ "code": 16386,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "StartUpOnOff",
+ "code": 16387,
+ "mfgCode": null,
+ "side": "server",
+ "type": "OnOffStartUpOnOff",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0xFF",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "FeatureMap",
+ "code": 65532,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap32",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "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": "4",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Level Control",
+ "code": 8,
+ "mfgCode": null,
+ "define": "LEVEL_CONTROL_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "MoveToLevel",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "Move",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "Step",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "Stop",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "MoveToLevelWithOnOff",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "MoveWithOnOff",
+ "code": 5,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "StepWithOnOff",
+ "code": 6,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "StopWithOnOff",
+ "code": 7,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "5",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Level Control",
+ "code": 8,
+ "mfgCode": null,
+ "define": "LEVEL_CONTROL_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "CurrentLevel",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x01",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RemainingTime",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "MinLevel",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x01",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "MaxLevel",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0xFE",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentFrequency",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "MinFrequency",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "MaxFrequency",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Options",
+ "code": 15,
+ "mfgCode": null,
+ "side": "server",
+ "type": "LevelControlOptions",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "OnOffTransitionTime",
+ "code": 16,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "OnLevel",
+ "code": 17,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0xFF",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "OnTransitionTime",
+ "code": 18,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "OffTransitionTime",
+ "code": 19,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "DefaultMoveRate",
+ "code": 20,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "50",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "StartUpCurrentLevel",
+ "code": 16384,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "255",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "GeneratedCommandList",
+ "code": 65528,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 0,
+ "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": 0,
+ "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": 0,
+ "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": "3",
+ "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": "5",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Descriptor",
+ "code": 29,
+ "mfgCode": null,
+ "define": "DESCRIPTOR_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "attributes": [
+ {
+ "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": "Descriptor",
+ "code": 29,
+ "mfgCode": null,
+ "define": "DESCRIPTOR_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "DeviceTypeList",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ServerList",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClientList",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PartsList",
+ "code": 3,
+ "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": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Basic Information",
+ "code": 40,
+ "mfgCode": null,
+ "define": "BASIC_INFORMATION_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Basic Information",
+ "code": 40,
+ "mfgCode": null,
+ "define": "BASIC_INFORMATION_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "DataModelRevision",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "10",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "VendorName",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "VendorID",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "vendor_id",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ProductName",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ProductID",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "NodeLabel",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "Location",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "XX",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "HardwareVersion",
+ "code": 7,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "HardwareVersionString",
+ "code": 8,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "SoftwareVersion",
+ "code": 9,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int32u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "SoftwareVersionString",
+ "code": 10,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ManufacturingDate",
+ "code": 11,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "20210614123456ZZ",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "PartNumber",
+ "code": 12,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ProductURL",
+ "code": 13,
+ "mfgCode": null,
+ "side": "server",
+ "type": "long_char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ProductLabel",
+ "code": 14,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "SerialNumber",
+ "code": 15,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "LocalConfigDisabled",
+ "code": 16,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "NVM",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "Reachable",
+ "code": 17,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "UniqueID",
+ "code": 18,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CapabilityMinima",
+ "code": 19,
+ "mfgCode": null,
+ "side": "server",
+ "type": "CapabilityMinimaStruct",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 1,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Color Control",
+ "code": 768,
+ "mfgCode": null,
+ "define": "COLOR_CONTROL_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "commands": [
+ {
+ "name": "MoveToHue",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "MoveHue",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "StepHue",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "MoveToSaturation",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "MoveSaturation",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "StepSaturation",
+ "code": 5,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "MoveToHueAndSaturation",
+ "code": 6,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "MoveToColor",
+ "code": 7,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "MoveColor",
+ "code": 8,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "StepColor",
+ "code": 9,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 1
+ },
+ {
+ "name": "MoveToColorTemperature",
+ "code": 10,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "EnhancedMoveToHue",
+ "code": 64,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "EnhancedMoveHue",
+ "code": 65,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "EnhancedStepHue",
+ "code": 66,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "EnhancedMoveToHueAndSaturation",
+ "code": 67,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "ColorLoopSet",
+ "code": 68,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "StopMoveStep",
+ "code": 71,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "MoveColorTemperature",
+ "code": 75,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ },
+ {
+ "name": "StepColorTemperature",
+ "code": 76,
+ "mfgCode": null,
+ "source": "client",
+ "incoming": 1,
+ "outgoing": 0
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "5",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Color Control",
+ "code": 768,
+ "mfgCode": null,
+ "define": "COLOR_CONTROL_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "attributes": [
+ {
+ "name": "CurrentHue",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentSaturation",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "RemainingTime",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentX",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x616B",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CurrentY",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x607D",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "DriftCompensation",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "enum8",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CompensationText",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "char_string",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorTemperatureMireds",
+ "code": 7,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00FA",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorMode",
+ "code": 8,
+ "mfgCode": null,
+ "side": "server",
+ "type": "enum8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x01",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "Options",
+ "code": 15,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "NumberOfPrimaries",
+ "code": 16,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary1X",
+ "code": 17,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary1Y",
+ "code": 18,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary1Intensity",
+ "code": 19,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary2X",
+ "code": 21,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary2Y",
+ "code": 22,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary2Intensity",
+ "code": 23,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary3X",
+ "code": 25,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary3Y",
+ "code": 26,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary3Intensity",
+ "code": 27,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary4X",
+ "code": 32,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary4Y",
+ "code": 33,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary4Intensity",
+ "code": 34,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary5X",
+ "code": 36,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary5Y",
+ "code": 37,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary5Intensity",
+ "code": 38,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary6X",
+ "code": 40,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary6Y",
+ "code": 41,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Primary6Intensity",
+ "code": 42,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "WhitePointX",
+ "code": 48,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "WhitePointY",
+ "code": 49,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorPointRX",
+ "code": 50,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorPointRY",
+ "code": 51,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorPointRIntensity",
+ "code": 52,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorPointGX",
+ "code": 54,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorPointGY",
+ "code": 55,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorPointGIntensity",
+ "code": 56,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorPointBX",
+ "code": 58,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorPointBY",
+ "code": 59,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorPointBIntensity",
+ "code": 60,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 0,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "EnhancedCurrentHue",
+ "code": 16384,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "EnhancedColorMode",
+ "code": 16385,
+ "mfgCode": null,
+ "side": "server",
+ "type": "enum8",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x01",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorLoopActive",
+ "code": 16386,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorLoopDirection",
+ "code": 16387,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x00",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorLoopTime",
+ "code": 16388,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0019",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorLoopStartEnhancedHue",
+ "code": 16389,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x2300",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorLoopStoredEnhancedHue",
+ "code": 16390,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorCapabilities",
+ "code": 16394,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap16",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x1F",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorTempPhysicalMinMireds",
+ "code": 16395,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0x0000",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "ColorTempPhysicalMaxMireds",
+ "code": 16396,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0xFEFF",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "CoupleColorTempToLevelMinMireds",
+ "code": 16397,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "StartUpColorTemperatureMireds",
+ "code": 16400,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "GeneratedCommandList",
+ "code": 65528,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 0,
+ "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": 0,
+ "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": 0,
+ "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": "0x1F",
+ "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": "5",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Occupancy Sensing",
+ "code": 1030,
+ "mfgCode": null,
+ "define": "OCCUPANCY_SENSING_CLUSTER",
+ "side": "client",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "client",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "3",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ },
+ {
+ "name": "Occupancy Sensing",
+ "code": 1030,
+ "mfgCode": null,
+ "define": "OCCUPANCY_SENSING_CLUSTER",
+ "side": "server",
+ "enabled": 0,
+ "attributes": [
+ {
+ "name": "Occupancy",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "OccupancyBitmap",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "OccupancySensorType",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "OccupancySensorTypeEnum",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ },
+ {
+ "name": "OccupancySensorTypeBitmap",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "OccupancySensorTypeBitmap",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "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": "3",
+ "reportable": 1,
+ "minInterval": 0,
+ "maxInterval": 65344,
+ "reportableChange": 0
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "endpoints": [
+ {
+ "endpointTypeName": "MA-rootdevice",
+ "endpointTypeIndex": 0,
+ "profileId": 259,
+ "endpointId": 0,
+ "networkId": 0,
+ "endpointVersion": 1,
+ "deviceIdentifier": 22
+ },
+ {
+ "endpointTypeName": "MA-dimmablelight",
+ "endpointTypeIndex": 1,
+ "profileId": 259,
+ "endpointId": 1,
+ "networkId": 0,
+ "endpointVersion": 1,
+ "deviceIdentifier": 257
+ }
+ ]
+}
\ No newline at end of file
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/.gn b/silabs_examples/Direct_Internet_lighting-app/efr32/.gn
new file mode 100644
index 00000000000000..4c078f6acefdcc
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/.gn
@@ -0,0 +1,29 @@
+# Copyright (c) 2020 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.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+ chip_openthread_ftd = true
+
+ import("//args.gni")
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/BUILD.gn b/silabs_examples/Direct_Internet_lighting-app/efr32/BUILD.gn
new file mode 100644
index 00000000000000..f625db4542444b
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/BUILD.gn
@@ -0,0 +1,189 @@
+# Copyright (c) 2020 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.
+
+import("//build_overrides/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${build_root}/config/defaults.gni")
+import("${efr32_sdk_build_root}/efr32_sdk.gni")
+import("${efr32_sdk_build_root}/silabs_executable.gni")
+
+import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni")
+import("${chip_root}/src/platform/device.gni")
+
+if (chip_enable_pw_rpc) {
+ import("//build_overrides/pigweed.gni")
+ import("$dir_pw_build/target_types.gni")
+}
+
+assert(current_os == "freertos")
+
+efr32_project_dir = "${chip_root}/silabs_examples/Direct_Internet_lighting-app/efr32"
+examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32"
+examples_common_plat_dir = "${chip_root}/examples/platform/silabs"
+
+if (chip_enable_ble_rs911x) {
+ src_plat_dir = "${chip_root}/src/platform/silabs/efr32"
+}
+
+import("${examples_plat_dir}/args.gni")
+
+declare_args() {
+ # Dump memory usage at link time.
+ chip_print_memory_usage = false
+}
+
+efr32_sdk("sdk") {
+ sources = [
+ "${efr32_project_dir}/include/CHIPProjectConfig.h",
+ "${examples_plat_dir}/FreeRTOSConfig.h",
+ ]
+
+ include_dirs = [
+ "${chip_root}/src/platform/silabs/efr32",
+ "${efr32_project_dir}/include",
+ "${examples_plat_dir}",
+ "${chip_root}/src/lib",
+ "${examples_common_plat_dir}",
+ ]
+
+ if (use_wf200) {
+ # TODO efr32_sdk should not need a header from this location
+ include_dirs += [ "${examples_plat_dir}/wf200" ]
+ }
+
+ if (chip_enable_ble_rs911x) {
+ # TODO efr32_sdk should not need a header from this location
+ include_dirs += [
+ "${src_plat_dir}/rs911x",
+ "${examples_plat_dir}/rs911x",
+ "${examples_plat_dir}/rs911x/hal",
+ ]
+ }
+
+ defines = []
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "HAL_VCOM_ENABLE=1",
+ "PW_RPC_ENABLED",
+ ]
+ }
+}
+
+silabs_executable("Direct_Internet_lighting_app") {
+ output_name = "chip-efr32-Direct_Internet_lighting-example.out"
+ public_configs = [ "${efr32_sdk_build_root}:silabs_config" ]
+ include_dirs = [ "include" ]
+ defines = []
+
+ if (silabs_board == "BRD2704A") {
+ defines += [ "SL_STATUS_LED=0" ]
+ }
+
+ sources = [
+ "src/AppTask.cpp",
+ "src/LightingManager.cpp",
+ "src/ZclCallbacks.cpp",
+ "src/main.cpp",
+ ]
+
+ deps = [
+ ":sdk",
+ "${examples_plat_dir}:efr32-common",
+ app_data_model,
+ ]
+
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "PW_RPC_ENABLED",
+ "PW_RPC_ATTRIBUTE_SERVICE=1",
+ "PW_RPC_BUTTON_SERVICE=1",
+ "PW_RPC_DESCRIPTOR_SERVICE=1",
+ "PW_RPC_DEVICE_SERVICE=1",
+ "PW_RPC_LIGHTING_SERVICE=1",
+ "PW_RPC_OTCLI_SERVICE=1",
+ "PW_RPC_THREAD_SERVICE=1",
+ "PW_RPC_TRACING_SERVICE=1",
+ ]
+
+ sources += [
+ "${chip_root}/examples/common/pigweed/RpcService.cpp",
+ "${chip_root}/examples/common/pigweed/efr32/PigweedLoggerMutex.cpp",
+ "${examples_common_plat_dir}/PigweedLogger.cpp",
+ "${examples_common_plat_dir}/Rpc.cpp",
+ ]
+
+ deps += [
+ "$dir_pw_hdlc:rpc_channel_output",
+ "$dir_pw_stream:sys_io_stream",
+ "$dir_pw_trace",
+ "$dir_pw_trace_tokenized",
+ "$dir_pw_trace_tokenized:trace_rpc_service",
+ "${chip_root}/config/efr32/lib/pw_rpc:pw_rpc",
+ "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:Direct_Internet_lighting_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:ot_cli_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:thread_service.nanopb_rpc",
+ "${examples_plat_dir}/pw_sys_io:pw_sys_io_efr32",
+ ]
+
+ deps += pw_build_LINK_DEPS
+
+ include_dirs += [
+ "${chip_root}/examples/common",
+ "${chip_root}/examples/common/pigweed/efr32",
+ ]
+ }
+
+ ldscript = "${examples_plat_dir}/ldscripts/${silabs_family}.ld"
+
+ inputs = [ ldscript ]
+
+ ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ]
+
+ if (chip_print_memory_usage) {
+ ldflags += [
+ "-Wl,--print-memory-usage",
+ "-fstack-usage",
+ ]
+ }
+
+ # WiFi Settings
+ if (chip_enable_wifi) {
+ ldflags += [
+ "-Wl,--defsym",
+ "-Wl,SILABS_WIFI=1",
+ ]
+ }
+
+ # MQTT
+ if (enable_dic) {
+ deps += [ "${examples_plat_dir}:efr32-dic" ]
+ }
+
+ output_dir = root_out_dir
+}
+
+group("efr32") {
+ deps = [ ":Direct_Internet_lighting_app" ]
+}
+
+group("default") {
+ deps = [ ":efr32" ]
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/README.md b/silabs_examples/Direct_Internet_lighting-app/efr32/README.md
new file mode 100644
index 00000000000000..2d9fe56590d115
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/README.md
@@ -0,0 +1,392 @@
+# Matter EFR32 Lighting Example
+
+An example showing the use of CHIP on the Silicon Labs EFR32 MG12 and MG24.
+
+
+
+- [Matter EFR32 Lighting Example](#matter-efr32-lighting-example)
+ - [Introduction](#introduction)
+ - [Building](#building)
+ - [Flashing the Application](#flashing-the-application)
+ - [Viewing Logging Output](#viewing-logging-output)
+ - [Running the Complete Example](#running-the-complete-example)
+ - [Notes](#notes)
+ - [Running RPC console](#running-rpc-console)
+ - [Device Tracing](#device-tracing)
+ - [Memory settings](#memory-settings)
+ - [OTA Software Update](#ota-software-update)
+ - [Group Communication (Multicast)](#group-communication-multicast)
+ - [Building options](#building-options)
+ - [Disabling logging](#disabling-logging)
+ - [Debug build / release build](#debug-build--release-build)
+ - [Disabling LCD](#disabling-lcd)
+ - [KVS maximum entry count](#kvs-maximum-entry-count)
+
+
+
+> **NOTE:** Silicon Laboratories now maintains a public matter GitHub repo with
+> frequent releases thoroughly tested and validated. Developers looking to
+> develop matter products with silabs hardware are encouraged to use our latest
+> release with added tools and documentation.
+> [Silabs Matter Github](https://github.com/SiliconLabs/matter/releases)
+
+## Introduction
+
+The EFR32 lighting example provides a baseline demonstration of a Light control
+device, built using Matter and the Silicon Labs gecko SDK. It can be controlled
+by a Chip controller over an Openthread or Wifi network..
+
+The EFR32 device can be commissioned over Bluetooth Low Energy where the device
+and the Chip controller will exchange security information with the Rendez-vous
+procedure. If using Thread, Thread Network credentials are then provided to the
+EFR32 device which will then join the Thread network.
+
+If the LCD is enabled, the LCD on the Silabs WSTK shows a QR Code containing the
+needed commissioning information for the BLE connection and starting the
+Rendez-vous procedure.
+
+The lighting example is intended to serve both as a means to explore the
+workings of Matter as well as a template for creating real products based on the
+Silicon Labs platform.
+
+## Building
+
+- Download the
+ [Simplicity Commander](https://www.silabs.com/mcu/programming-options)
+ command line tool, and ensure that `commander` is your shell search path.
+ (For Mac OS X, `commander` is located inside
+ `Commander.app/Contents/MacOS/`.)
+
+- Download and install a suitable ARM gcc tool chain:
+ [GNU Arm Embedded Toolchain 9-2019-q4-major](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads)
+
+- Install some additional tools (likely already present for CHIP developers):
+
+ - Linux: `sudo apt-get install git ninja-build`
+
+ - Mac OS X: `brew install ninja`
+
+- Supported hardware:
+
+ - > For the latest supported hardware please refer to the
+ > [Hardware Requirements](https://github.com/SiliconLabs/matter/blob/latest/docs/silabs/general/HARDWARE_REQUIREMENTS.md)
+ > in the Silicon Labs Matter Github Repo
+
+ MG12 boards:
+
+ - BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+ 868MHz@19dBm
+ - BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+ - BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm
+ - BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm,
+ 915MHz@19dBm
+ - BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm
+
+ MG21 boards: Currently not supported due to RAM limitation.
+
+ - BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+ MG24 boards :
+
+ - BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+ - BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+ - BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+* Build the example application:
+
+ cd ~/connectedhomeip
+ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/silabs/efr32/ ./out/lighting-app BRD4161A
+
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/connectedhomeip
+ $ rm -rf ./out/
+
+ OR use GN/Ninja directly
+
+ $ cd ~/connectedhomeip/examples/lighting-app/silabs/efr32
+ $ git submodule update --init
+ $ source third_party/connectedhomeip/scripts/activate.sh
+ $ export silabs_board=BRD4161A
+ $ gn gen out/debug
+ $ ninja -C out/debug
+
+- To delete generated executable, libraries and object files use:
+
+ $ cd ~/connectedhomeip/examples/lighting-app/silabs/efr32
+ $ rm -rf out/
+
+* Build the example as Sleepy End Device (SED)
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/silabs/efr32/ ./out/lighting-app_SED BRD4161A --sed
+
+ or use gn as previously mentioned but adding the following arguments:
+
+ $ gn gen out/debug '--args=silabs_board="BRD4161A" enable_sleepy_device=true chip_openthread_ftd=false'
+
+* Build the example with pigweed RPC
+
+ $ ./scripts/examples/gn_efr32_example.sh examples/lighting-app/silabs/efr32/ out/lighting_app_rpc BRD4161A 'import("//with_pw_rpc.gni")'
+
+ or use GN/Ninja Directly
+
+ $ cd ~/connectedhomeip/examples/lighting-app/silabs/efr32
+ $ git submodule update --init
+ $ source third_party/connectedhomeip/scripts/activate.sh
+ $ export silabs_board=BRD4161A
+ $ gn gen out/debug --args='import("//with_pw_rpc.gni")'
+ $ ninja -C out/debug
+
+ [Running Pigweed RPC console](#running-rpc-console)
+
+For more build options, help is provided when running the build script without
+arguments
+
+ ./scripts/examples/gn_efr32_example.sh
+
+## Flashing the Application
+
+- On the command line:
+
+ $ cd ~/connectedhomeip/examples/lighting-app/silabs/efr32
+ $ python3 out/debug/chip-efr32-lighting-example.flash.py
+
+- Or with the Ozone debugger, just load the .out file.
+
+All EFR32 boards require a bootloader, see Silicon Labs documentation for more
+info. Pre-built bootloader binaries are available in the Assets section of the
+Releases page on
+[Silabs Matter Github](https://github.com/SiliconLabs/matter/releases) .
+
+## Viewing Logging Output
+
+The example application is built to use the SEGGER Real Time Transfer (RTT)
+facility for log output. RTT is a feature built-in to the J-Link Interface MCU
+on the WSTK development board. It allows bi-directional communication with an
+embedded application without the need for a dedicated UART.
+
+Using the RTT facility requires downloading and installing the _SEGGER J-Link
+Software and Documentation Pack_
+([web site](https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack)).
+
+Alternatively, SEGGER Ozone J-Link debugger can be used to view RTT logs too
+after flashing the .out file.
+
+- Download the J-Link installer by navigating to the appropriate URL and
+ agreeing to the license agreement.
+
+- [JLink_Linux_x86_64.deb](https://www.segger.com/downloads/jlink/JLink_Linux_x86_64.deb)
+- [JLink_MacOSX.pkg](https://www.segger.com/downloads/jlink/JLink_MacOSX.pkg)
+
+* Install the J-Link software
+
+ $ cd ~/Downloads
+ $ sudo dpkg -i JLink_Linux_V*_x86_64.deb
+
+* In Linux, grant the logged in user the ability to talk to the development
+ hardware via the linux tty device (/dev/ttyACMx) by adding them to the
+ dialout group.
+
+ $ sudo usermod -a -G dialout ${USER}
+
+Once the above is complete, log output can be viewed using the JLinkExe tool in
+combination with JLinkRTTClient as follows:
+
+- Run the JLinkExe tool with arguments to autoconnect to the WSTK board:
+
+ For MG12 use:
+
+ $ JLinkExe -device EFR32MG12PXXXF1024 -if JTAG -speed 4000 -autoconnect 1
+
+ For MG21 use:
+
+ $ JLinkExe -device EFR32MG21AXXXF1024 -if SWD -speed 4000 -autoconnect 1
+
+- In a second terminal, run the JLinkRTTClient to view logs:
+
+ $ JLinkRTTClient
+
+## Running the Complete Example
+
+- It is assumed here that you already have an OpenThread border router
+ configured and running. If not see the following guide
+ [Openthread_border_router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md)
+ for more information on how to setup a border router on a raspberryPi.
+
+ Take note that the RCP code is available directly through
+ [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio/simplicity-studio-5)
+ under File->New->Project Wizard->Examples->Thread : ot-rcp
+
+- User interface : **LCD** The LCD on Silabs WSTK shows a QR Code. This QR
+ Code is be scanned by the CHIP Tool app For the Rendez-vous procedure over
+ BLE
+
+ * On devices that do not have or support the LCD Display like the BRD4166A Thunderboard Sense 2,
+ a URL can be found in the RTT logs.
+
+ [SVR] Copy/paste the below URL in a browser to see the QR Code:
+ [SVR] https://project-chip.github.io/connectedhomeip/qrcode.html?data=CH%3AI34NM%20-00%200C9SS0
+
+ **LED 0** shows the overall state of the device and its connectivity. The
+ following states are possible:
+
+ - _Short Flash On (50 ms on/950 ms off)_ ; The device is in the
+ unprovisioned (unpaired) state and is waiting for a commissioning
+ application to connect.
+
+ - _Rapid Even Flashing_ ; (100 ms on/100 ms off)_ — The device is in the
+ unprovisioned state and a commissioning application is connected through
+ Bluetooth LE.
+
+ - _Short Flash Off_ ; (950ms on/50ms off)_ — The device is fully
+ provisioned, but does not yet have full Thread network or service
+ connectivity.
+
+ - _Solid On_ ; The device is fully provisioned and has full Thread
+ network and service connectivity.
+
+ **LED 1** Simulates the Light The following states are possible:
+
+ - _Solid On_ ; Light is on
+ - _Off_ ; Light is off
+
+ **Push Button 0**
+
+ - _Press and Release_ : Start, or restart, BLE advertisement in fast mode. It will advertise in this mode
+ for 30 seconds. The device will then switch to a slower interval advertisement.
+ After 15 minutes, the advertisement stops.
+
+ - _Pressed and hold for 6 s_ : Initiates the factory reset of the device.
+ Releasing the button within the 6-second window cancels the factory reset
+ procedure. **LEDs** blink in unison when the factory reset procedure is
+ initiated.
+
+ **Push Button 1** Toggles the light state On/Off
+
+* You can provision and control the Chip device using the python controller,
+ Chip tool standalone, Android or iOS app
+
+* You can provision and control the Chip device using the python controller,
+ Chip tool standalone, Android or iOS app
+
+ [CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md)
+
+ Here is an example with the CHIPTool:
+
+ chip-tool pairing ble-thread 1 hex: 20202021 3840
+
+ chip-tool onoff on 1 1
+
+### Notes
+
+- Depending on your network settings your router might not provide native ipv6
+ addresses to your devices (Border router / PC). If this is the case, you
+ need to add a static ipv6 addresses on both device and then an ipv6 route to
+ the border router on your PC
+
+ - On Border Router: `sudo ip addr add dev 2002::2/64`
+
+ - On PC(Linux): `sudo ip addr add dev 2002::1/64`
+
+ - Add Ipv6 route on PC(Linux)
+ `sudo ip route add /64 via 2002::2`
+
+## Running RPC console
+
+- As part of building the example with RPCs enabled the chip_rpc python
+ interactive console is installed into your venv. The python wheel files are
+ also created in the output folder: out/debug/chip_rpc_console_wheels. To
+ install the wheel files without rebuilding:
+ `pip3 install out/debug/chip_rpc_console_wheels/*.whl`
+
+- To use the chip-rpc console after it has been installed run:
+ `chip-console --device /dev/tty. -b 115200 -o //pw_log.out`
+
+- Then you can simulate a button press or release using the following command
+ where : idx = 0 or 1 for Button PB0 or PB1 action = 0 for PRESSED, 1 for
+ RELEASE Test toggling the LED with
+ `rpcs.chip.rpc.Button.Event(idx=1, pushed=True)`
+
+- You can also Get and Set the light directly using the RPCs:
+ `rpcs.chip.rpc.Lighting.Get()`
+
+ `rpcs.chip.rpc.Lighting.Set(on=True, level=128, color=protos.chip.rpc.LightingColor(hue=5, saturation=5))`
+
+## Device Tracing
+
+Device tracing is available to analyze the device performance. To turn on
+tracing, build with RPC enabled. See Build the example with pigweed RPC.
+
+Obtain tracing json file.
+
+ $ ./{PIGWEED_REPO}/pw_trace_tokenized/py/pw_trace_tokenized/get_trace.py -d {PORT} -o {OUTPUT_FILE} \
+ -t {ELF_FILE} {PIGWEED_REPO}/pw_trace_tokenized/pw_trace_protos/trace_rpc.proto
+
+## Memory settings
+
+While most of the RAM usage in CHIP is static, allowing easier debugging and
+optimization with symbols analysis, we still need some HEAP for the crypto and
+OpenThread. Size of the HEAP can be modified by changing the value of the
+`configTOTAL_HEAP_SIZE` define inside of the FreeRTOSConfig.h file of this
+example. Please take note that a HEAP size smaller than 13k can and will cause a
+Mbedtls failure during the BLE rendez-vous or CASE session
+
+To track memory usage you can set `enable_heap_monitoring = true` either in the
+BUILD.gn file or pass it as a build argument to gn. This will print on the RTT
+console the RAM usage of each individual task and the number of Memory
+allocation and Free. While this is not extensive monitoring you're welcome to
+modify `examples/platform/silabs/efr32/MemMonitoring.cpp` to add your own memory
+tracking code inside the `trackAlloc` and `trackFree` function
+
+## OTA Software Update
+
+For the description of Software Update process with EFR32 example applications
+see
+[EFR32 OTA Software Update](../../../../docs/guides/silabs_efr32_software_update.md)
+
+## Group Communication (Multicast)
+
+With this lighting example you can also use group communication to send Lighting
+commands to multiples devices at once. Please refer to the
+[chip-tool documentation](../../../chip-tool/README.md) _Configuring the server
+side for Group Commands_ and _Using the Client to Send Group (Multicast) Matter
+Commands_
+
+## Building options
+
+All of Silabs's examples within the Matter repo have all the features enabled by
+default, as to provide the best end user experience. However some of those
+features can easily be toggled on or off. Here is a short list of options to be
+passed to the build scripts.
+
+### Disabling logging
+
+`chip_progress_logging, chip_detail_logging, chip_automation_logging`
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/silabs/efr32 ./out/lighting-app BRD4164A "chip_detail_logging=false chip_automation_logging=false chip_progress_logging=false"
+
+### Debug build / release build
+
+`is_debug`
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/silabs/efr32 ./out/lighting-app BRD4164A "is_debug=false"
+
+### Disabling LCD
+
+`show_qr_code`
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/silabs/efr32 ./out/lighting-app BRD4164A "show_qr_code=false"
+
+### KVS maximum entry count
+
+`kvs_max_entries`
+
+ Set the maximum Kvs entries that can be stored in NVM (Default 75)
+ Thresholds: 30 <= kvs_max_entries <= 255
+
+ $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/silabs/efr32 ./out/lighting-app BRD4164A kvs_max_entries=50
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/args.gni b/silabs_examples/Direct_Internet_lighting-app/efr32/args.gni
new file mode 100644
index 00000000000000..ed143fcd9aa99c
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/args.gni
@@ -0,0 +1,27 @@
+# Copyright (c) 2020 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.
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+import("${chip_root}/src/platform/silabs/efr32/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+app_data_model =
+ "${chip_root}/silabs_examples/Direct_Internet_lighting-app/data_model"
+chip_enable_ota_requestor = true
+chip_enable_openthread = true
+
+openthread_external_platform =
+ "${chip_root}/third_party/openthread/platforms/efr32:libopenthread-efr32"
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/build_for_wifi_args.gni b/silabs_examples/Direct_Internet_lighting-app/efr32/build_for_wifi_args.gni
new file mode 100644
index 00000000000000..909b2a1ebe1904
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/build_for_wifi_args.gni
@@ -0,0 +1,23 @@
+# Copyright (c) 2020 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.
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/standalone/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+chip_enable_openthread = false
+import("${chip_root}/src/platform/silabs/efr32/wifi_args.gni")
+
+chip_enable_ota_requestor = true
+app_data_model =
+ "${chip_root}/silabs_examples/Direct_Internet_lighting-app/data_model:silabs-lighting"
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/build_for_wifi_gnfile.gn b/silabs_examples/Direct_Internet_lighting-app/efr32/build_for_wifi_gnfile.gn
new file mode 100644
index 00000000000000..d391814190d09f
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/build_for_wifi_gnfile.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2020 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.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+ chip_enable_wifi = true
+ import("//build_for_wifi_args.gni")
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/build_overrides b/silabs_examples/Direct_Internet_lighting-app/efr32/build_overrides
new file mode 120000
index 00000000000000..f2758328a72777
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/build_overrides
@@ -0,0 +1 @@
+../../../examples/build_overrides
\ No newline at end of file
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/include/AppConfig.h b/silabs_examples/Direct_Internet_lighting-app/efr32/include/AppConfig.h
new file mode 100644
index 00000000000000..349f28d7c466d6
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/include/AppConfig.h
@@ -0,0 +1,86 @@
+/*
+ *
+ * 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 "efr32_utils.h"
+
+// ---- Lighting Example App Config ----
+
+#define APP_TASK_NAME "Lit"
+
+// Time it takes in ms for the simulated actuator to move from one
+// state to another.
+#define ACTUATOR_MOVEMENT_PERIOS_MS 10
+
+#define ON_DEMO_BITMAP \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, \
+ 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0x1f, 0xfe, 0x07, 0xe0, \
+ 0x7f, 0xf8, 0xff, 0xff, 0x3f, 0xfc, 0x00, 0x00, 0x3f, 0xfc, 0xff, 0xff, 0x7f, 0x3c, 0xe0, 0x07, 0x3c, 0xfe, 0xff, 0xff, \
+ 0xff, 0x1f, 0xfe, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, \
+ 0xe3, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, \
+ 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, \
+ 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xff, 0x0f, 0x38, 0xfe, 0xff, 0xff, 0x7f, 0x1c, 0xf0, 0x0f, 0x38, 0xfe, 0x03, 0xc0, 0x7f, 0x1c, 0xf0, 0x0f, \
+ 0x38, 0xfe, 0x27, 0xe9, 0x7f, 0x1c, 0xf0, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xe7, 0xe7, 0x7f, 0xfc, 0xff, 0xff, 0x7f, 0xfe, 0xef, 0xf7, 0x7f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xef, 0xf7, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0xef, 0xf3, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xcf, 0xf3, \
+ 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xdf, 0xfb, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xdf, 0xfb, 0x8f, 0xff, 0xff, 0xff, \
+ 0xff, 0xe3, 0x9f, 0xf9, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x9f, 0xf9, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x9f, 0xfd, \
+ 0xe3, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xbf, 0xfd, 0xf1, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0xfc, 0xf8, 0xff, 0xff, 0xff, \
+ 0xff, 0x3f, 0x3e, 0x7c, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f, \
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x3f, 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
+
+#define OFF_DEMO_BITMAP \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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, 0xe0, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x07, 0xfc, 0xff, 0xff, 0xff, \
+ 0xff, 0x1f, 0xfe, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, \
+ 0xe3, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, \
+ 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, \
+ 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, \
+ 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, \
+ 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, \
+ 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, \
+ 0xff, 0xe3, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, \
+ 0xe3, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, \
+ 0xff, 0x3f, 0xfe, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f, \
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0x3f, 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
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/include/AppEvent.h b/silabs_examples/Direct_Internet_lighting-app/efr32/include/AppEvent.h
new file mode 100644
index 00000000000000..7a19b719edad25
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/include/AppEvent.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2018 Nest Labs, Inc.
+ * 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
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+ enum AppEventTypes
+ {
+ kEventType_Button = 0,
+ kEventType_Timer,
+ kEventType_Light,
+ kEventType_Install,
+ };
+
+ uint16_t Type;
+
+ union
+ {
+ struct
+ {
+ uint8_t Action;
+ } ButtonEvent;
+ struct
+ {
+ void * Context;
+ } TimerEvent;
+ struct
+ {
+ uint8_t Action;
+ int32_t Actor;
+ } LightEvent;
+ };
+
+ EventHandler Handler;
+};
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/include/AppTask.h b/silabs_examples/Direct_Internet_lighting-app/efr32/include/AppTask.h
new file mode 100644
index 00000000000000..cc76b02e8b293d
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/include/AppTask.h
@@ -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.
+ */
+
+#pragma once
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include
+#include
+
+#include "AppEvent.h"
+#include "BaseApplication.h"
+#include "FreeRTOS.h"
+#include "LightingManager.h"
+#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
+#include "sl_simple_button_instances.h"
+#endif
+#include "timers.h" // provides FreeRTOS timer support
+#include
+#include
+#include
+#include
+
+/**********************************************************
+ * Defines
+ *********************************************************/
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+
+/**********************************************************
+ * AppTask Declaration
+ *********************************************************/
+
+class AppTask : public BaseApplication
+{
+
+public:
+ AppTask() = default;
+
+ static AppTask & GetAppTask() { return sAppTask; }
+
+ /**
+ * @brief AppTask task main loop function
+ *
+ * @param pvParameter FreeRTOS task parameter
+ */
+ static void AppTaskMain(void * pvParameter);
+
+ CHIP_ERROR StartAppTask();
+#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
+ /**
+ * @brief Event handler when a button is pressed
+ * Function posts an event for button processing
+ *
+ * @param buttonHandle APP_LIGHT_SWITCH or APP_FUNCTION_BUTTON
+ * @param btnAction button action - SL_SIMPLE_BUTTON_PRESSED,
+ * SL_SIMPLE_BUTTON_RELEASED or SL_SIMPLE_BUTTON_DISABLED
+ */
+ void ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction) override;
+#endif
+ /**
+ * @brief Callback called by the identify-server when an identify command is received
+ *
+ * @param identify identify structure the command applies on
+ */
+ static void OnIdentifyStart(Identify * identify);
+
+ /**
+ * @brief Callback called by the identify-server when an identify command is stopped or finished
+ *
+ * @param identify identify structure the command applies on
+ */
+ static void OnIdentifyStop(Identify * identify);
+
+ void PostLightActionRequest(int32_t aActor, LightingManager::Action_t aAction);
+
+private:
+ static AppTask sAppTask;
+
+ static void ActionInitiated(LightingManager::Action_t aAction, int32_t aActor);
+ static void ActionCompleted(LightingManager::Action_t aAction);
+ static void LightActionEventHandler(AppEvent * aEvent);
+
+ static void UpdateClusterState(intptr_t context);
+
+ /**
+ * @brief AppTask initialisation function
+ *
+ * @return CHIP_ERROR
+ */
+ CHIP_ERROR Init();
+
+ /**
+ * @brief PB0 Button event processing function
+ * Press and hold will trigger a factory reset timer start
+ * Press and release will restart BLEAdvertising if not commisionned
+ *
+ * @param aEvent button event being processed
+ */
+ static void ButtonHandler(AppEvent * aEvent);
+
+ /**
+ * @brief PB1 Button event processing function
+ * Function triggers a switch action sent to the CHIP task
+ *
+ * @param aEvent button event being processed
+ */
+ static void SwitchActionEventHandler(AppEvent * aEvent);
+};
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/include/CHIPProjectConfig.h b/silabs_examples/Direct_Internet_lighting-app/efr32/include/CHIPProjectConfig.h
new file mode 100644
index 00000000000000..00df921596102a
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/include/CHIPProjectConfig.h
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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.
+ */
+
+/**
+ * @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.
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+#endif
+
+// For convenience, Chip Security Test Mode can be enabled and the
+// requirement for authentication in various protocols can be disabled.
+//
+// WARNING: These options make it possible to circumvent basic Chip security functionality,
+// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
+//
+#define CHIP_CONFIG_SECURITY_TEST_MODE 0
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ * 0x8005: example lighting app
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ *
+ * Enable support for Chip-over-BLE (CHIPoBLE).
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+
+/**
+ * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
+ *
+ * Enables the use of a hard-coded default serial number if none
+ * is found in Chip NV storage.
+ */
+#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
+ *
+ * Enable recording UTC timestamps.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE
+ *
+ * A size, in bytes, of the individual debug event logging buffer.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512)
+
+/**
+ * @def CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL
+ *
+ * @brief
+ * Active retransmit interval, or time to wait before retransmission after
+ * subsequent failures in milliseconds.
+ *
+ * This is the default value, that might be adjusted by end device depending on its
+ * needs (e.g. sleeping period) using Service Discovery TXT record CRA key.
+ *
+ */
+#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32)
+
+#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/include/LightingManager.h b/silabs_examples/Direct_Internet_lighting-app/efr32/include/LightingManager.h
new file mode 100644
index 00000000000000..6d286faa30ef96
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/include/LightingManager.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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
+#include
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include
+
+#include
+
+class LightingManager
+{
+public:
+ enum Action_t
+ {
+ ON_ACTION = 0,
+ OFF_ACTION,
+
+ INVALID_ACTION
+ } Action;
+
+ enum State_t
+ {
+ kState_OffInitiated = 0,
+ kState_OffCompleted,
+ kState_OnInitiated,
+ kState_OnCompleted,
+ } State;
+
+ CHIP_ERROR Init();
+ bool IsLightOn();
+ void EnableAutoTurnOff(bool aOn);
+ void SetAutoTurnOffDuration(uint32_t aDurationInSecs);
+ bool IsActionInProgress();
+ bool InitiateAction(int32_t aActor, Action_t aAction);
+
+ typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor);
+ typedef void (*Callback_fn_completed)(Action_t);
+ void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB);
+
+ static void OnTriggerOffWithEffect(OnOffEffect * effect);
+
+private:
+ friend LightingManager & LightMgr(void);
+ State_t mState;
+
+ Callback_fn_initiated mActionInitiated_CB;
+ Callback_fn_completed mActionCompleted_CB;
+
+ bool mAutoTurnOff;
+ uint32_t mAutoTurnOffDuration;
+ bool mAutoTurnOffTimerArmed;
+ bool mOffEffectArmed;
+
+ void CancelTimer(void);
+ void StartTimer(uint32_t aTimeoutMs);
+
+ static void TimerEventHandler(TimerHandle_t xTimer);
+ static void AutoTurnOffTimerEventHandler(AppEvent * aEvent);
+ static void ActuatorMovementTimerEventHandler(AppEvent * aEvent);
+ static void OffEffectTimerEventHandler(AppEvent * aEvent);
+
+ static LightingManager sLight;
+};
+
+inline LightingManager & LightMgr(void)
+{
+ return LightingManager::sLight;
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/src/AppTask.cpp b/silabs_examples/Direct_Internet_lighting-app/efr32/src/AppTask.cpp
new file mode 100644
index 00000000000000..9deb94b079dd7f
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/src/AppTask.cpp
@@ -0,0 +1,380 @@
+/*
+ *
+ * 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 "AppTask.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+
+#ifdef ENABLE_WSTK_LEDS
+#include "LEDWidget.h"
+#include "sl_simple_led_instances.h"
+#endif // ENABLE_WSTK_LEDS
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+
+#include
+
+#ifdef DIC_ENABLE
+#include "dic.h"
+#endif
+
+#ifdef ENABLE_WSTK_LEDS
+#if defined(SL_CATALOG_SIMPLE_LED_LED1_PRESENT)
+#define LIGHT_LED &sl_led_led1
+#else
+#define LIGHT_LED &sl_led_led0
+#endif
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
+
+#define APP_FUNCTION_BUTTON &sl_button_btn0
+#define APP_LIGHT_SWITCH &sl_button_btn1
+#endif
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+namespace {
+
+#ifdef ENABLE_WSTK_LEDS
+LEDWidget sLightLED;
+#endif // ENABLE_WSTK_LEDS
+
+EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+/**********************************************************
+ * Identify Callbacks
+ *********************************************************/
+
+namespace {
+void OnTriggerIdentifyEffectCompleted(chip::System::Layer * systemLayer, void * appState)
+{
+ ChipLogProgress(Zcl, "Trigger Identify Complete");
+ sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ AppTask::GetAppTask().StopStatusLEDTimer();
+#endif
+}
+} // namespace
+
+#ifdef DIC_ENABLE
+namespace {
+void AppSpecificConnectivityEventCallback(const ChipDeviceEvent * event, intptr_t arg)
+{
+ SILABS_LOG("AppSpecificConnectivityEventCallback: call back for IPV4");
+ if ((event->Type == DeviceEventType::kInternetConnectivityChange) &&
+ (event->InternetConnectivityChange.IPv4 == kConnectivity_Established))
+ {
+ SILABS_LOG("Got IPv4 Address! Starting DIC module\n");
+ if (DIC_OK != DIC_Init())
+ SILABS_LOG("Failed to initialize DIC module\n");
+ }
+}
+}
+#endif
+
+void OnTriggerIdentifyEffect(Identify * identify)
+{
+ sIdentifyEffect = identify->mCurrentEffectIdentifier;
+
+ if (identify->mCurrentEffectIdentifier == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE)
+ {
+ ChipLogProgress(Zcl, "IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE - Not supported, use effect varriant %d",
+ identify->mEffectVariant);
+ sIdentifyEffect = static_cast(identify->mEffectVariant);
+ }
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ AppTask::GetAppTask().StartStatusLEDTimer();
+#endif
+
+ switch (sIdentifyEffect)
+ {
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK:
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE:
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY:
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(5), OnTriggerIdentifyEffectCompleted,
+ identify);
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT:
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(1), OnTriggerIdentifyEffectCompleted,
+ identify);
+ break;
+ case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT:
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+ break;
+ default:
+ ChipLogProgress(Zcl, "No identifier effect");
+ }
+}
+
+Identify gIdentify = {
+ chip::EndpointId{ 1 },
+ AppTask::GetAppTask().OnIdentifyStart,
+ AppTask::GetAppTask().OnIdentifyStop,
+ EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED,
+ OnTriggerIdentifyEffect,
+};
+
+} // namespace
+
+using namespace chip::TLV;
+using namespace ::chip::DeviceLayer;
+
+AppTask AppTask::sAppTask;
+
+CHIP_ERROR AppTask::Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+#ifdef DISPLAY_ENABLED
+ GetLCD().Init((uint8_t *) "Lighting-App");
+#endif
+
+ err = BaseApplication::Init(&gIdentify);
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("BaseApplication::Init() failed");
+ appError(err);
+ }
+
+ err = LightMgr().Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("LightMgr::Init() failed");
+ appError(err);
+ }
+
+ LightMgr().SetCallbacks(ActionInitiated, ActionCompleted);
+
+#ifdef DIC_ENABLE
+ chip::DeviceLayer::PlatformMgr().AddEventHandler(AppSpecificConnectivityEventCallback, reinterpret_cast(nullptr));
+#endif
+#ifdef ENABLE_WSTK_LEDS
+ sLightLED.Init(LIGHT_LED);
+ sLightLED.Set(LightMgr().IsLightOn());
+#endif // ENABLE_WSTK_LEDS
+
+// Update the LCD with the Stored value. Show QR Code if not provisioned
+#ifdef DISPLAY_ENABLED
+ GetLCD().WriteDemoUI(LightMgr().IsLightOn());
+#ifdef QR_CODE_ENABLED
+#ifdef SL_WIFI
+ if (!ConnectivityMgr().IsWiFiStationProvisioned())
+#else
+ if (!ConnectivityMgr().IsThreadProvisioned())
+#endif /* !SL_WIFI */
+ {
+ GetLCD().ShowQRCode(true, true);
+ }
+#endif // QR_CODE_ENABLED
+#endif
+
+ return err;
+}
+
+CHIP_ERROR AppTask::StartAppTask()
+{
+ return BaseApplication::StartAppTask(AppTaskMain);
+}
+
+void AppTask::AppTaskMain(void * pvParameter)
+{
+ AppEvent event;
+ QueueHandle_t sAppEventQueue = *(static_cast(pvParameter));
+
+ CHIP_ERROR err = sAppTask.Init();
+ if (err != CHIP_NO_ERROR)
+ {
+ SILABS_LOG("AppTask.Init() failed");
+ appError(err);
+ }
+
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+ sAppTask.StartStatusLEDTimer();
+#endif
+
+ SILABS_LOG("App Task started");
+
+ while (true)
+ {
+ BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, portMAX_DELAY);
+ while (eventReceived == pdTRUE)
+ {
+ sAppTask.DispatchEvent(&event);
+ eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
+ }
+ }
+}
+
+void AppTask::OnIdentifyStart(Identify * identify)
+{
+ ChipLogProgress(Zcl, "onIdentifyStart");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ sAppTask.StartStatusLEDTimer();
+#endif
+}
+
+void AppTask::OnIdentifyStop(Identify * identify)
+{
+ ChipLogProgress(Zcl, "onIdentifyStop");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+ sAppTask.StopStatusLEDTimer();
+#endif
+}
+
+void AppTask::LightActionEventHandler(AppEvent * aEvent)
+{
+ bool initiated = false;
+ LightingManager::Action_t action;
+ int32_t actor;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ if (aEvent->Type == AppEvent::kEventType_Light)
+ {
+ action = static_cast(aEvent->LightEvent.Action);
+ actor = aEvent->LightEvent.Actor;
+ }
+#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
+ else if (aEvent->Type == AppEvent::kEventType_Button)
+ {
+ action = (LightMgr().IsLightOn()) ? LightingManager::OFF_ACTION : LightingManager::ON_ACTION;
+ actor = AppEvent::kEventType_Button;
+ }
+#endif
+ else
+ {
+ err = APP_ERROR_UNHANDLED_EVENT;
+ }
+
+ if (err == CHIP_NO_ERROR)
+ {
+ initiated = LightMgr().InitiateAction(actor, action);
+
+ if (!initiated)
+ {
+ SILABS_LOG("Action is already in progress or active.");
+ }
+ }
+}
+#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
+void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction)
+{
+ if (buttonHandle == NULL)
+ {
+ return;
+ }
+
+ AppEvent button_event = {};
+ button_event.Type = AppEvent::kEventType_Button;
+ button_event.ButtonEvent.Action = btnAction;
+
+ if (buttonHandle == APP_LIGHT_SWITCH && btnAction == SL_SIMPLE_BUTTON_PRESSED)
+ {
+ button_event.Handler = LightActionEventHandler;
+ sAppTask.PostEvent(&button_event);
+ }
+ else if (buttonHandle == APP_FUNCTION_BUTTON)
+ {
+ button_event.Handler = BaseApplication::ButtonHandler;
+ sAppTask.PostEvent(&button_event);
+ }
+}
+
+#endif
+
+void AppTask::ActionInitiated(LightingManager::Action_t aAction, int32_t aActor)
+{
+ // Action initiated, update the light led
+ bool lightOn = aAction == LightingManager::ON_ACTION;
+ SILABS_LOG("Turning light %s", (lightOn) ? "On" : "Off")
+
+#ifdef ENABLE_WSTK_LEDS
+ sLightLED.Set(lightOn);
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef DISPLAY_ENABLED
+ sAppTask.GetLCD().WriteDemoUI(lightOn);
+#endif
+#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
+ if (aActor == AppEvent::kEventType_Button)
+ {
+ sAppTask.mSyncClusterToButtonAction = true;
+ }
+#endif
+}
+
+void AppTask::ActionCompleted(LightingManager::Action_t aAction)
+{
+ // action has been completed bon the light
+ if (aAction == LightingManager::ON_ACTION)
+ {
+ SILABS_LOG("Light ON")
+ }
+ else if (aAction == LightingManager::OFF_ACTION)
+ {
+ SILABS_LOG("Light OFF")
+ }
+#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
+ if (sAppTask.mSyncClusterToButtonAction)
+ {
+ chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterState, reinterpret_cast(nullptr));
+ sAppTask.mSyncClusterToButtonAction = false;
+ }
+#endif
+}
+
+void AppTask::PostLightActionRequest(int32_t aActor, LightingManager::Action_t aAction)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Light;
+ event.LightEvent.Actor = aActor;
+ event.LightEvent.Action = aAction;
+ event.Handler = LightActionEventHandler;
+ PostEvent(&event);
+}
+
+void AppTask::UpdateClusterState(intptr_t context)
+{
+ uint8_t newValue = LightMgr().IsLightOn();
+
+ // write the new on/off value
+ EmberAfStatus status = OnOffServer::Instance().setOnOffValue(1, newValue, false);
+
+ if (status != EMBER_ZCL_STATUS_SUCCESS)
+ {
+ SILABS_LOG("ERR: updating on/off %x", status);
+ }
+}
\ No newline at end of file
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/src/LightingManager.cpp b/silabs_examples/Direct_Internet_lighting-app/efr32/src/LightingManager.cpp
new file mode 100644
index 00000000000000..2c5807f4ea693e
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/src/LightingManager.cpp
@@ -0,0 +1,322 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LightingManager.h"
+
+#include "AppConfig.h"
+#include "AppTask.h"
+#include
+
+#include
+
+using namespace chip;
+using namespace ::chip::app::Clusters::OnOff;
+using namespace ::chip::DeviceLayer;
+
+LightingManager LightingManager::sLight;
+
+TimerHandle_t sLightTimer;
+
+namespace {
+
+/**********************************************************
+ * OffWithEffect Callbacks
+ *********************************************************/
+
+OnOffEffect gEffect = {
+ chip::EndpointId{ 1 },
+ LightMgr().OnTriggerOffWithEffect,
+ OnOffEffectIdentifier::kDelayedAllOff,
+ to_underlying(OnOffDelayedAllOffEffectVariant::kFadeToOffIn0p8Seconds),
+};
+
+} // namespace
+
+CHIP_ERROR LightingManager::Init()
+{
+ // Create FreeRTOS sw timer for light timer.
+ sLightTimer = xTimerCreate("lightTmr", // Just a text name, not used by the RTOS kernel
+ pdMS_TO_TICKS(1), // == default timer period
+ false, // no timer reload (==one-shot)
+ (void *) this, // init timer id = light obj context
+ TimerEventHandler // timer callback handler
+ );
+
+ if (sLightTimer == NULL)
+ {
+ SILABS_LOG("sLightTimer timer create failed");
+ return APP_ERROR_CREATE_TIMER_FAILED;
+ }
+
+ bool currentLedState;
+ // read current on/off value on endpoint one.
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ OnOffServer::Instance().getOnOffValue(1, ¤tLedState);
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ mState = currentLedState ? kState_OnCompleted : kState_OffCompleted;
+ mAutoTurnOffTimerArmed = false;
+ mAutoTurnOff = false;
+ mAutoTurnOffDuration = 0;
+ mOffEffectArmed = false;
+
+ return CHIP_NO_ERROR;
+}
+
+void LightingManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
+{
+ mActionInitiated_CB = aActionInitiated_CB;
+ mActionCompleted_CB = aActionCompleted_CB;
+}
+
+bool LightingManager::IsActionInProgress()
+{
+ return (mState == kState_OffInitiated || mState == kState_OnInitiated);
+}
+
+bool LightingManager::IsLightOn()
+{
+ return (mState == kState_OnCompleted);
+}
+
+void LightingManager::EnableAutoTurnOff(bool aOn)
+{
+ mAutoTurnOff = aOn;
+}
+
+void LightingManager::SetAutoTurnOffDuration(uint32_t aDurationInSecs)
+{
+ mAutoTurnOffDuration = aDurationInSecs;
+}
+
+bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction)
+{
+ bool action_initiated = false;
+ State_t new_state;
+
+ // Initiate Turn On/Off Action only when the previous one is complete.
+ if (((mState == kState_OffCompleted) || mOffEffectArmed) && aAction == ON_ACTION)
+ {
+ action_initiated = true;
+
+ new_state = kState_OnInitiated;
+ }
+ else if (mState == kState_OnCompleted && aAction == OFF_ACTION && mOffEffectArmed == false)
+ {
+ action_initiated = true;
+
+ new_state = kState_OffInitiated;
+ }
+
+ if (action_initiated)
+ {
+ if (mAutoTurnOffTimerArmed && new_state == kState_OffInitiated)
+ {
+ // If auto turn off timer has been armed and someone initiates turning off,
+ // cancel the timer and continue as normal.
+ mAutoTurnOffTimerArmed = false;
+
+ CancelTimer();
+ }
+
+ if (mOffEffectArmed && new_state == kState_OnInitiated)
+ {
+ CancelTimer();
+ mOffEffectArmed = false;
+ }
+
+ StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
+
+ // Since the timer started successfully, update the state and trigger callback
+ mState = new_state;
+
+ if (mActionInitiated_CB)
+ {
+ mActionInitiated_CB(aAction, aActor);
+ }
+ }
+
+ return action_initiated;
+}
+
+void LightingManager::StartTimer(uint32_t aTimeoutMs)
+{
+ if (xTimerIsTimerActive(sLightTimer))
+ {
+ SILABS_LOG("app timer already started!");
+ CancelTimer();
+ }
+
+ // timer is not active, change its period to required value (== restart).
+ // FreeRTOS- Block for a maximum of 100 ms if the change period command
+ // cannot immediately be sent to the timer command queue.
+ if (xTimerChangePeriod(sLightTimer, pdMS_TO_TICKS(aTimeoutMs), pdMS_TO_TICKS(100)) != pdPASS)
+ {
+ SILABS_LOG("sLightTimer timer start() failed");
+ appError(APP_ERROR_START_TIMER_FAILED);
+ }
+}
+
+void LightingManager::CancelTimer(void)
+{
+ if (xTimerStop(sLightTimer, pdMS_TO_TICKS(0)) == pdFAIL)
+ {
+ SILABS_LOG("sLightTimer stop() failed");
+ appError(APP_ERROR_STOP_TIMER_FAILED);
+ }
+}
+
+void LightingManager::TimerEventHandler(TimerHandle_t xTimer)
+{
+ // Get light obj context from timer id.
+ LightingManager * light = static_cast(pvTimerGetTimerID(xTimer));
+
+ // The timer event handler will be called in the context of the timer task
+ // once sLightTimer expires. Post an event to apptask queue with the actual handler
+ // so that the event can be handled in the context of the apptask.
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.Context = light;
+ if (light->mAutoTurnOffTimerArmed)
+ {
+ event.Handler = AutoTurnOffTimerEventHandler;
+ }
+ else if (light->mOffEffectArmed)
+ {
+ event.Handler = OffEffectTimerEventHandler;
+ }
+ else
+ {
+ event.Handler = ActuatorMovementTimerEventHandler;
+ }
+ AppTask::GetAppTask().PostEvent(&event);
+}
+
+void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent)
+{
+ LightingManager * light = static_cast(aEvent->TimerEvent.Context);
+ int32_t actor = AppEvent::kEventType_Timer;
+
+ // Make sure auto turn off timer is still armed.
+ if (!light->mAutoTurnOffTimerArmed)
+ {
+ return;
+ }
+
+ light->mAutoTurnOffTimerArmed = false;
+
+ SILABS_LOG("Auto Turn Off has been triggered!");
+
+ light->InitiateAction(actor, OFF_ACTION);
+}
+
+void LightingManager::OffEffectTimerEventHandler(AppEvent * aEvent)
+{
+ LightingManager * light = static_cast(aEvent->TimerEvent.Context);
+ int32_t actor = AppEvent::kEventType_Timer;
+
+ // Make sure auto turn off timer is still armed.
+ if (!light->mOffEffectArmed)
+ {
+ return;
+ }
+
+ light->mOffEffectArmed = false;
+
+ SILABS_LOG("OffEffect completed");
+
+ light->InitiateAction(actor, OFF_ACTION);
+}
+
+void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
+{
+ Action_t actionCompleted = INVALID_ACTION;
+
+ LightingManager * light = static_cast(aEvent->TimerEvent.Context);
+
+ if (light->mState == kState_OffInitiated)
+ {
+ light->mState = kState_OffCompleted;
+ actionCompleted = OFF_ACTION;
+ }
+ else if (light->mState == kState_OnInitiated)
+ {
+ light->mState = kState_OnCompleted;
+ actionCompleted = ON_ACTION;
+ }
+
+ if (actionCompleted != INVALID_ACTION)
+ {
+ if (light->mActionCompleted_CB)
+ {
+ light->mActionCompleted_CB(actionCompleted);
+ }
+
+ if (light->mAutoTurnOff && actionCompleted == ON_ACTION)
+ {
+ // Start the timer for auto turn off
+ light->StartTimer(light->mAutoTurnOffDuration * 1000);
+
+ light->mAutoTurnOffTimerArmed = true;
+
+ SILABS_LOG("Auto Turn off enabled. Will be triggered in %u seconds", light->mAutoTurnOffDuration);
+ }
+ }
+}
+
+void LightingManager::OnTriggerOffWithEffect(OnOffEffect * effect)
+{
+ auto effectId = effect->mEffectIdentifier;
+ auto effectVariant = effect->mEffectVariant;
+ uint32_t offEffectDuration = 0;
+
+ // Temporary print outs and delay to test OffEffect behaviour
+ // Until dimming is supported for dev boards.
+ if (effectId == OnOffEffectIdentifier::kDelayedAllOff)
+ {
+ auto typedEffectVariant = static_cast(effectVariant);
+ if (typedEffectVariant == OnOffDelayedAllOffEffectVariant::kFadeToOffIn0p8Seconds)
+ {
+ offEffectDuration = 800;
+ ChipLogProgress(Zcl, "OnOffDelayedAllOffEffectVariant::kFadeToOffIn0p8Seconds");
+ }
+ else if (typedEffectVariant == OnOffDelayedAllOffEffectVariant::kNoFade)
+ {
+ offEffectDuration = 800;
+ ChipLogProgress(Zcl, "OnOffDelayedAllOffEffectVariant::kNoFade");
+ }
+ else if (typedEffectVariant == OnOffDelayedAllOffEffectVariant::k50PercentDimDownIn0p8SecondsThenFadeToOffIn12Seconds)
+ {
+ offEffectDuration = 12800;
+ ChipLogProgress(Zcl, "OnOffDelayedAllOffEffectVariant::k50PercentDimDownIn0p8SecondsThenFadeToOffIn12Seconds");
+ }
+ }
+ else if (effectId == OnOffEffectIdentifier::kDyingLight)
+ {
+ auto typedEffectVariant = static_cast(effectVariant);
+ if (typedEffectVariant == OnOffDyingLightEffectVariant::k20PercenterDimUpIn0p5SecondsThenFadeToOffIn1Second)
+ {
+ offEffectDuration = 1500;
+ ChipLogProgress(Zcl, "OnOffDyingLightEffectVariant::k20PercenterDimUpIn0p5SecondsThenFadeToOffIn1Second");
+ }
+ }
+
+ LightMgr().mOffEffectArmed = true;
+ LightMgr().StartTimer(offEffectDuration);
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/src/ZclCallbacks.cpp b/silabs_examples/Direct_Internet_lighting-app/efr32/src/ZclCallbacks.cpp
new file mode 100644
index 00000000000000..aa7caedb5e7d82
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/src/ZclCallbacks.cpp
@@ -0,0 +1,103 @@
+/*
+ *
+ * Copyright (c) 2020 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.
+ */
+
+/**
+ * @file
+ * This file implements the handler for data model messages.
+ */
+
+#include "AppConfig.h"
+#include "LightingManager.h"
+#ifdef DIC_ENABLE
+#include "dic.h"
+#endif
+
+#include
+#include
+#include
+#include
+
+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));
+#ifdef DIC_ENABLE
+ if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
+ {
+ dic_buff_t buffValue;
+
+ buffValue.dataP = (uint8_t *)(value ? ( *value ? "on" : "off") : "invalid");
+ buffValue.dataLen = strlen((const char *)buffValue.dataP);
+ DIC_SendMsg("light/state", &buffValue);
+ }
+#endif
+ if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
+ {
+ LightMgr().InitiateAction(AppEvent::kEventType_Light, *value ? LightingManager::ON_ACTION : LightingManager::OFF_ACTION);
+ }
+ else if (clusterId == LevelControl::Id)
+ {
+ ChipLogProgress(Zcl, "Level Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (clusterId == ColorControl::Id)
+ {
+ ChipLogProgress(Zcl, "Color Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (clusterId == OnOffSwitchConfiguration::Id)
+ {
+ ChipLogProgress(Zcl, "OnOff Switch Configuration attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+ ChipLogValueMEI(attributeId), type, *value, size);
+
+ // WIP Apply attribute change to Light
+ }
+ else if (clusterId == Identify::Id)
+ {
+ 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
+}
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/src/main.cpp b/silabs_examples/Direct_Internet_lighting-app/efr32/src/main.cpp
new file mode 100644
index 00000000000000..9f447b972678b6
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/src/main.cpp
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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
+
+#include "AppConfig.h"
+#include "init_efrPlatform.h"
+#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
+#include "sl_simple_button_instances.h"
+#endif
+#include "sl_system_kernel.h"
+#include
+#include
+#include
+#include
+#ifdef EFR32_ATTESTATION_CREDENTIALS
+#include
+#else
+#include
+#endif
+
+#define BLE_DEV_NAME "SiLabs-Light"
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::Credentials;
+
+#define UNUSED_PARAMETER(a) (a = a)
+
+volatile int apperror_cnt;
+static chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+
+// ================================================================================
+// Main Code
+// ================================================================================
+int main(void)
+{
+ init_efrPlatform();
+ if (EFR32MatterConfig::InitMatter(BLE_DEV_NAME) != CHIP_NO_ERROR)
+ appError(CHIP_ERROR_INTERNAL);
+
+ gExampleDeviceInfoProvider.SetStorageDelegate(&chip::Server::GetInstance().GetPersistentStorage());
+ chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
+ chip::DeviceLayer::PlatformMgr().LockChipStack();
+ // Initialize device attestation config
+#ifdef EFR32_ATTESTATION_CREDENTIALS
+ SetDeviceAttestationCredentialsProvider(Silabs::GetSilabsDacProvider());
+#else
+ SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
+ chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+ SILABS_LOG("Starting App Task");
+ if (AppTask::GetAppTask().StartAppTask() != CHIP_NO_ERROR)
+ appError(CHIP_ERROR_INTERNAL);
+
+ SILABS_LOG("Starting FreeRTOS scheduler");
+ sl_system_kernel_start();
+
+ // Should never get here.
+ chip::Platform::MemoryShutdown();
+ SILABS_LOG("vTaskStartScheduler() failed");
+ appError(CHIP_ERROR_INTERNAL);
+}
+
+#ifdef SL_CATALOG_SIMPLE_BUTTON_PRESENT
+void sl_button_on_change(const sl_button_t * handle)
+{
+ AppTask::GetAppTask().ButtonEventHandler(handle, sl_button_get_state(handle));
+}
+#endif
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/third_party/connectedhomeip b/silabs_examples/Direct_Internet_lighting-app/efr32/third_party/connectedhomeip
new file mode 120000
index 00000000000000..c866b86874994d
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../..
\ No newline at end of file
diff --git a/silabs_examples/Direct_Internet_lighting-app/efr32/with_pw_rpc.gni b/silabs_examples/Direct_Internet_lighting-app/efr32/with_pw_rpc.gni
new file mode 100644
index 00000000000000..40a8bb79d84b6a
--- /dev/null
+++ b/silabs_examples/Direct_Internet_lighting-app/efr32/with_pw_rpc.gni
@@ -0,0 +1,31 @@
+# Copyright (c) 2021 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.
+
+# add this gni as import in your build args to use pigweed in the example
+# 'import("//with_pw_rpc.gni")'
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/efr32/lib/pw_rpc/pw_rpc.gni")
+import("${chip_root}/examples/platform/silabs/efr32/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_pw_rpc = true
+chip_enable_openthread = true
+chip_build_pw_trace_lib = true
+
+cpp_standard = "gnu++17"
+
+# Light app on EFR enables tracing server
+pw_trace_BACKEND = "$dir_pw_trace_tokenized"
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/include/MQTT_transport.h b/third_party/silabs/mqtt/mqtt_transport_interface/include/MQTT_transport.h
new file mode 100644
index 00000000000000..5c5575562a0f8d
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/include/MQTT_transport.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright (c) 2023 Project CHIP Authors
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef MQTT_TRANSPORT_H
+#define MQTT_TRANSPORT_H
+
+#include "mqtt_opts.h"
+#include "lwip/err.h"
+#include "lwip/ip_addr.h"
+#include "mqtt.h"
+#include "altcp_tls.h"
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "semphr.h"
+
+#define SIGNAL_TRANSINTF_MBEDTLS_RX 0x80
+#define SIGNAL_TRANSINTF_RX 0x01
+#define SIGNAL_TRANSINTF_TX_ACK 0x02
+#define SIGNAL_TRANSINTF_CONN_CLOSE 0x04
+
+typedef void (*dic_connect_cb)(err_t);
+typedef struct MQTT_Transport_t MQTT_Transport_t;
+void transport_process_mbedtls_rx(MQTT_Transport_t *client);
+MQTT_Transport_t * MQTT_Transport_Init(mqtt_transport_intf_t *trans,mqtt_client_t* mqtt_client,EventGroupHandle_t dicEvents);
+err_t MQTT_Transport_SSLConfigure(MQTT_Transport_t * transP, const u8_t *ca, size_t ca_len, const u8_t *privkey, size_t privkey_len,
+ const u8_t *privkey_pass, size_t privkey_pass_len,
+ const u8_t *cert, size_t cert_len);
+err_t MQTT_Transport_Connect(MQTT_Transport_t* client,const char *host, u16_t port, dic_connect_cb dic_con_cb);
+
+#endif //MQTT_TRANSPORT_H
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp.h b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp.h
new file mode 100644
index 00000000000000..c594ff8f1f3875
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp.h
@@ -0,0 +1,224 @@
+/**
+ * @file
+ * Application layered TCP connection API (to be used from TCPIP thread)\n
+ *
+ * This file contains the generic API.
+ * For more details see @ref altcp_api.
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+#ifndef TRANSPORT_HDR_ALTCP_H
+#define TRANSPORT_HDR_ALTCP_H
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#include "lwip/tcpbase.h"
+#include "lwip/tcp.h"
+#include "lwip/err.h"
+#include "lwip/pbuf.h"
+#include "lwip/ip_addr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct altcp_pcb;
+struct altcp_functions;
+
+typedef err_t (*altcp_accept_fn)(void *arg, struct altcp_pcb *new_conn, err_t err);
+typedef err_t (*altcp_connected_fn)(void *arg, struct altcp_pcb *conn, err_t err);
+typedef err_t (*altcp_recv_fn)(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err);
+typedef err_t (*altcp_sent_fn)(void *arg, struct altcp_pcb *conn, u16_t len);
+typedef err_t (*altcp_poll_fn)(void *arg, struct altcp_pcb *conn);
+typedef void (*altcp_err_fn)(void *arg, err_t err);
+
+typedef struct altcp_pcb* (*altcp_new_fn)(void *arg, u8_t ip_type);
+
+struct altcp_pcb {
+ const struct altcp_functions *fns;
+ struct altcp_pcb *inner_conn;
+ void *arg;
+ void *state;
+ /* application callbacks */
+ altcp_accept_fn accept;
+ altcp_connected_fn connected;
+ altcp_recv_fn recv;
+ altcp_sent_fn sent;
+ altcp_poll_fn poll;
+ altcp_err_fn err;
+ u8_t pollinterval;
+};
+
+/** @ingroup altcp */
+typedef struct altcp_allocator_s {
+ /** Allocator function */
+ altcp_new_fn alloc;
+ /** Argument to allocator function */
+ void *arg;
+} altcp_allocator_t;
+
+//#define LWIP_DBG_ON 0x80U
+#define ALTCP_DEBUG
+//#define ALTCP_MBEDTLS_DEBUG (LWIP_DBG_ON)
+
+#ifndef TRANSPORT_UNUSED_ARG
+#define TRANSPORT_UNUSED_ARG(x) (void)x
+#endif /* TRANSPORT_UNUSED_ARG */
+#define TRANSPORT_MIN(x , y) (((x) < (y)) ? (x) : (y))
+#define TRANSPORT_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
+ x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
+#define TRANSPORT_ASSERT(message, assertion) do { if (!(assertion)) { \
+ TRANSPORT_PLATFORM_ASSERT(message); }} while(0)
+#ifdef TRANSPORT_DEBUG
+extern void efr32Log(const char * aFormat, ...);
+#define TRANSPORT_DEBUGF(x) efr32Log x;
+#else
+#define TRANSPORT_DEBUGF(x)
+#endif
+#define TRANSPORT_ERROR(message, expression, handler) do { if (!(expression)) { \
+ printf("Assertion \"%s\" failed at line %d in %s\n", message, __LINE__, __FILE__); \
+ fflush(NULL);handler;} } while(0)
+
+struct altcp_pcb *altcp_new(altcp_allocator_t *allocator);
+struct altcp_pcb *altcp_new_ip6(altcp_allocator_t *allocator);
+struct altcp_pcb *altcp_new_ip_type(altcp_allocator_t *allocator, u8_t ip_type);
+
+void altcp_arg(struct altcp_pcb *conn, void *arg);
+void altcp_accept(struct altcp_pcb *conn, altcp_accept_fn accept);
+void altcp_recv(struct altcp_pcb *conn, altcp_recv_fn recv);
+void altcp_sent(struct altcp_pcb *conn, altcp_sent_fn sent);
+void altcp_poll(struct altcp_pcb *conn, altcp_poll_fn poll, u8_t interval);
+void altcp_err(struct altcp_pcb *conn, altcp_err_fn err);
+
+void altcp_recved(struct altcp_pcb *conn, u16_t len);
+err_t altcp_bind(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port);
+err_t altcp_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected);
+
+/* return conn for source code compatibility to tcp callback API only */
+struct altcp_pcb *altcp_listen_with_backlog_and_err(struct altcp_pcb *conn, u8_t backlog, err_t *err);
+#define altcp_listen_with_backlog(conn, backlog) altcp_listen_with_backlog_and_err(conn, backlog, NULL)
+/** @ingroup altcp */
+#define altcp_listen(conn) altcp_listen_with_backlog_and_err(conn, TCP_DEFAULT_LISTEN_BACKLOG, NULL)
+
+void altcp_abort(struct altcp_pcb *conn);
+err_t altcp_close(struct altcp_pcb *conn);
+err_t altcp_shutdown(struct altcp_pcb *conn, int shut_rx, int shut_tx);
+
+err_t altcp_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags);
+err_t altcp_output(struct altcp_pcb *conn);
+
+u16_t altcp_mss(struct altcp_pcb *conn);
+u16_t altcp_sndbuf(struct altcp_pcb *conn);
+u16_t altcp_sndqueuelen(struct altcp_pcb *conn);
+void altcp_nagle_disable(struct altcp_pcb *conn);
+void altcp_nagle_enable(struct altcp_pcb *conn);
+int altcp_nagle_disabled(struct altcp_pcb *conn);
+
+void altcp_setprio(struct altcp_pcb *conn, u8_t prio);
+
+err_t altcp_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port);
+ip_addr_t *altcp_get_ip(struct altcp_pcb *conn, int local);
+u16_t altcp_get_port(struct altcp_pcb *conn, int local);
+
+#ifdef ALTCP_DEBUG
+enum tcp_state altcp_dbg_get_tcp_state(struct altcp_pcb *conn);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* TRANSPORT_ALTCP */
+
+/* ALTCP disabled, define everything to link against tcp callback API (e.g. to get a small non-ssl httpd) */
+
+#include "lwip/tcp.h"
+
+#define altcp_accept_fn tcp_accept_fn
+#define altcp_connected_fn tcp_connected_fn
+#define altcp_recv_fn tcp_recv_fn
+#define altcp_sent_fn tcp_sent_fn
+#define altcp_poll_fn tcp_poll_fn
+#define altcp_err_fn tcp_err_fn
+
+#define altcp_pcb tcp_pcb
+#define altcp_tcp_new_ip_type tcp_new_ip_type
+#define altcp_tcp_new tcp_new
+#define altcp_tcp_new_ip6 tcp_new_ip6
+
+#define altcp_new(allocator) tcp_new()
+#define altcp_new_ip6(allocator) tcp_new_ip6()
+#define altcp_new_ip_type(allocator, ip_type) tcp_new_ip_type(ip_type)
+
+#define altcp_arg tcp_arg
+#define altcp_accept tcp_accept
+#define altcp_recv tcp_recv
+#define altcp_sent tcp_sent
+#define altcp_poll tcp_poll
+#define altcp_err tcp_err
+
+#define altcp_recved tcp_recved
+#define altcp_bind tcp_bind
+#define altcp_connect tcp_connect
+
+#define altcp_listen_with_backlog_and_err tcp_listen_with_backlog_and_err
+#define altcp_listen_with_backlog tcp_listen_with_backlog
+#define altcp_listen tcp_listen
+
+#define altcp_abort tcp_abort
+#define altcp_close tcp_close
+#define altcp_shutdown tcp_shutdown
+
+#define altcp_write tcp_write
+#define altcp_output tcp_output
+
+#define altcp_mss tcp_mss
+#define altcp_sndbuf tcp_sndbuf
+#define altcp_sndqueuelen tcp_sndqueuelen
+#define altcp_nagle_disable tcp_nagle_disable
+#define altcp_nagle_enable tcp_nagle_enable
+#define altcp_nagle_disabled tcp_nagle_disabled
+#define altcp_setprio tcp_setprio
+
+#define altcp_get_tcp_addrinfo tcp_get_tcp_addrinfo
+#define altcp_get_ip(pcb, local) ((local) ? (&(pcb)->local_ip) : (&(pcb)->remote_ip))
+
+#ifdef ALTCP_DEBUG
+#define altcp_dbg_get_tcp_state tcp_dbg_get_tcp_state
+#endif
+
+#endif /* TRANSPORT_ALTCP */
+
+#endif /* TRANSPORT_HDR_ALTCP_H */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_opt.h b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_opt.h
new file mode 100644
index 00000000000000..7080335d887532
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_opt.h
@@ -0,0 +1,28 @@
+/*
+ *
+ * Copyright (c) 2023 Project CHIP Authors
+ * Copyright (c) 2022 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.
+ */
+
+#ifndef __ALTCP_OPTS_H__
+#define __ALTCP_OPTS_H__
+
+#define TRANSPORT_ALTCP 1
+#define TRANSPORT_ALTCP_TLS 1
+#define TRANSPORT_ALTCP_TLS_MBEDTLS 1
+#define TRANSPORT_DEBUG 1
+
+#endif
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_priv.h b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_priv.h
new file mode 100644
index 00000000000000..8c4b7b1fc21082
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_priv.h
@@ -0,0 +1,146 @@
+/**
+ * @file
+ * Application layered TCP connection API (to be used from TCPIP thread)\n
+ * This interface mimics the tcp callback API to the application while preventing
+ * direct linking (much like virtual functions).
+ * This way, an application can make use of other application layer protocols
+ * on top of TCP without knowing the details (e.g. TLS, proxy connection).
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+#ifndef TRANSPORT_HDR_ALTCP_PRIV_H
+#define TRANSPORT_HDR_ALTCP_PRIV_H
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#include "altcp.h"
+#include "lwip/ip_addr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct altcp_pcb *altcp_alloc(void);
+void altcp_free(struct altcp_pcb *conn);
+
+/* Function prototypes for application layers */
+typedef void (*altcp_set_poll_fn)(struct altcp_pcb *conn, u8_t interval);
+typedef void (*altcp_recved_fn)(struct altcp_pcb *conn, u16_t len);
+typedef err_t (*altcp_bind_fn)(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port);
+typedef err_t (*altcp_connect_fn)(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected);
+
+typedef struct altcp_pcb *(*altcp_listen_fn)(struct altcp_pcb *conn, u8_t backlog, err_t *err);
+
+typedef void (*altcp_abort_fn)(struct altcp_pcb *conn);
+typedef err_t (*altcp_close_fn)(struct altcp_pcb *conn);
+typedef err_t (*altcp_shutdown_fn)(struct altcp_pcb *conn, int shut_rx, int shut_tx);
+
+typedef err_t (*altcp_write_fn)(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags);
+typedef err_t (*altcp_output_fn)(struct altcp_pcb *conn);
+
+typedef u16_t (*altcp_mss_fn)(struct altcp_pcb *conn);
+typedef u16_t (*altcp_sndbuf_fn)(struct altcp_pcb *conn);
+typedef u16_t (*altcp_sndqueuelen_fn)(struct altcp_pcb *conn);
+typedef void (*altcp_nagle_disable_fn)(struct altcp_pcb *conn);
+typedef void (*altcp_nagle_enable_fn)(struct altcp_pcb *conn);
+typedef int (*altcp_nagle_disabled_fn)(struct altcp_pcb *conn);
+
+typedef void (*altcp_setprio_fn)(struct altcp_pcb *conn, u8_t prio);
+
+typedef void (*altcp_dealloc_fn)(struct altcp_pcb *conn);
+
+typedef err_t (*altcp_get_tcp_addrinfo_fn)(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port);
+typedef ip_addr_t *(*altcp_get_ip_fn)(struct altcp_pcb *conn, int local);
+typedef u16_t (*altcp_get_port_fn)(struct altcp_pcb *conn, int local);
+
+#ifdef ALTCP_DEBUG
+typedef enum tcp_state (*altcp_dbg_get_tcp_state_fn)(struct altcp_pcb *conn);
+#endif
+
+struct altcp_functions {
+ altcp_set_poll_fn set_poll;
+ altcp_recved_fn recved;
+ altcp_bind_fn bind;
+ altcp_connect_fn connect;
+ altcp_listen_fn listen;
+ altcp_abort_fn abort;
+ altcp_close_fn close;
+ altcp_shutdown_fn shutdown;
+ altcp_write_fn write;
+ altcp_output_fn output;
+ altcp_mss_fn mss;
+ altcp_sndbuf_fn sndbuf;
+ altcp_sndqueuelen_fn sndqueuelen;
+ altcp_nagle_disable_fn nagle_disable;
+ altcp_nagle_enable_fn nagle_enable;
+ altcp_nagle_disabled_fn nagle_disabled;
+ altcp_setprio_fn setprio;
+ altcp_dealloc_fn dealloc;
+ altcp_get_tcp_addrinfo_fn addrinfo;
+ altcp_get_ip_fn getip;
+ altcp_get_port_fn getport;
+#ifdef ALTCP_DEBUG
+ altcp_dbg_get_tcp_state_fn dbg_get_tcp_state;
+#endif
+};
+
+void altcp_default_set_poll(struct altcp_pcb *conn, u8_t interval);
+void altcp_default_recved(struct altcp_pcb *conn, u16_t len);
+err_t altcp_default_bind(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port);
+err_t altcp_default_shutdown(struct altcp_pcb *conn, int shut_rx, int shut_tx);
+err_t altcp_default_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags);
+err_t altcp_default_output(struct altcp_pcb *conn);
+u16_t altcp_default_mss(struct altcp_pcb *conn);
+u16_t altcp_default_sndbuf(struct altcp_pcb *conn);
+u16_t altcp_default_sndqueuelen(struct altcp_pcb *conn);
+void altcp_default_nagle_disable(struct altcp_pcb *conn);
+void altcp_default_nagle_enable(struct altcp_pcb *conn);
+int altcp_default_nagle_disabled(struct altcp_pcb *conn);
+void altcp_default_setprio(struct altcp_pcb *conn, u8_t prio);
+void altcp_default_dealloc(struct altcp_pcb *conn);
+err_t altcp_default_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port);
+ip_addr_t *altcp_default_get_ip(struct altcp_pcb *conn, int local);
+u16_t altcp_default_get_port(struct altcp_pcb *conn, int local);
+#ifdef ALTCP_DEBUG
+enum tcp_state altcp_default_dbg_get_tcp_state(struct altcp_pcb *conn);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TARNSPORT_ALTCP */
+
+#endif /* TRANSPORT_HDR_ALTCP_PRIV_H */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tcp.h b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tcp.h
new file mode 100644
index 00000000000000..b0f82f3321186b
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tcp.h
@@ -0,0 +1,72 @@
+/**
+ * @file
+ * Application layered TCP connection API (to be used from TCPIP thread)\n
+ * This interface mimics the tcp callback API to the application while preventing
+ * direct linking (much like virtual functions).
+ * This way, an application can make use of other application layer protocols
+ * on top of TCP without knowing the details (e.g. TLS, proxy connection).
+ *
+ * This file contains the base implementation calling into tcp.
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+#ifndef TRANSPORT_HDR_ALTCP_TCP_H
+#define TRANSPORT_HDR_ALTCP_TCP_H
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#include "altcp.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct altcp_pcb *altcp_tcp_new_ip_type(u8_t ip_type);
+
+#define altcp_tcp_new() altcp_tcp_new_ip_type(IPADDR_TYPE_V4)
+#define altcp_tcp_new_ip6() altcp_tcp_new_ip_type(IPADDR_TYPE_V6)
+
+struct altcp_pcb *altcp_tcp_alloc(void *arg, u8_t ip_type);
+
+struct tcp_pcb;
+struct altcp_pcb *altcp_tcp_wrap(struct tcp_pcb *tpcb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TRANSPORT_ALTCP */
+
+#endif /* TRANSPORT_HDR_ALTCP_TCP_H */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls.h b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls.h
new file mode 100644
index 00000000000000..5eb83c7f48fdab
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls.h
@@ -0,0 +1,116 @@
+/**
+ * @file
+ * Application layered TCP/TLS connection API (to be used from TCPIP thread)
+ *
+ * @defgroup altcp_tls TLS layer
+ * @ingroup altcp
+ * This file contains function prototypes for a TLS layer.
+ * A port to ARM mbedtls is provided in the apps/ tree
+ * (TRANSPORT_ALTCP_TLS_MBEDTLS option).
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+#ifndef TRANSPORT_HDR_ALTCP_TLS_H
+#define TRANSPORT_HDR_ALTCP_TLS_H
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#if TRANSPORT_ALTCP_TLS
+
+#include "altcp.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @ingroup altcp_tls
+ * ALTCP_TLS configuration handle, content depends on port (e.g. mbedtls)
+ */
+struct altcp_tls_config;
+
+/** @ingroup altcp_tls
+ * Create an ALTCP_TLS server configuration handle
+ */
+struct altcp_tls_config *altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len,
+ const u8_t *privkey_pass, size_t privkey_pass_len,
+ const u8_t *cert, size_t cert_len);
+
+/** @ingroup altcp_tls
+ * Create an ALTCP_TLS client configuration handle
+ */
+struct altcp_tls_config *altcp_tls_create_config_client(const u8_t *cert, size_t cert_len);
+
+/** @ingroup altcp_tls
+ * Create an ALTCP_TLS client configuration handle with two-way server/client authentication
+ */
+struct altcp_tls_config *altcp_tls_create_config_client_2wayauth(const u8_t *ca, size_t ca_len, const u8_t *privkey, size_t privkey_len,
+ const u8_t *privkey_pass, size_t privkey_pass_len,
+ const u8_t *cert, size_t cert_len);
+/** @ingroup altcp_tls
+ * Free an ALTCP_TLS configuration handle
+ */
+void altcp_tls_free_config(struct altcp_tls_config *conf);
+
+/** @ingroup altcp_tls
+ * Create new ALTCP_TLS layer wrapping an existing pcb as inner connection (e.g. TLS over TCP)
+ */
+struct altcp_pcb *altcp_tls_wrap(struct altcp_tls_config *config, struct altcp_pcb *inner_pcb);
+
+/** @ingroup altcp_tls
+ * Create new ALTCP_TLS pcb and its inner tcp pcb
+ */
+struct altcp_pcb *altcp_tls_new(struct altcp_tls_config *config, u8_t ip_type);
+
+/** @ingroup altcp_tls
+ * Create new ALTCP_TLS layer pcb and its inner tcp pcb.
+ * Same as @ref altcp_tls_new but this allocator function fits to
+ * @ref altcp_allocator_t / @ref altcp_new.\n
+ 'arg' must contain a struct altcp_tls_config *.
+ */
+struct altcp_pcb *altcp_tls_alloc(void *arg, u8_t ip_type);
+
+/** @ingroup altcp_tls
+ * Return pointer to internal TLS context so application can tweak it.
+ * Real type depends on port (e.g. mbedtls)
+ */
+void *altcp_tls_context(struct altcp_pcb *conn);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TRANSPORT_ALTCP_TLS */
+#endif /* TRANSPORT_ALTCP */
+#endif /* TRANSPORT_HDR_ALTCP_TLS_H */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls_mbedtls_mem.h b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls_mbedtls_mem.h
new file mode 100644
index 00000000000000..3a3ea9c99c6db8
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls_mbedtls_mem.h
@@ -0,0 +1,72 @@
+/**
+ * @file
+ * Application layered TCP/TLS connection API (to be used from TCPIP thread)
+ *
+ * This file contains memory management function prototypes for a TLS layer using mbedTLS.
+ *
+ * Memory management contains:
+ * - allocating/freeing altcp_mbedtls_state_t
+ * - allocating/freeing memory used in the mbedTLS library
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+#ifndef LWIP_HDR_ALTCP_MBEDTLS_MEM_H
+#define LWIP_HDR_ALTCP_MBEDTLS_MEM_H
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#include "altcp_tls_mbedtls_opts.h"
+
+#if TRANSPORT_ALTCP_TLS && TRANSPORT_ALTCP_TLS_MBEDTLS
+
+#include "altcp_tls_mbedtls_structs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void altcp_mbedtls_mem_init(void);
+altcp_mbedtls_state_t *altcp_mbedtls_alloc(void *conf);
+void altcp_mbedtls_free(void *conf, altcp_mbedtls_state_t *state);
+void *altcp_mbedtls_alloc_config(size_t size);
+void altcp_mbedtls_free_config(void *item);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TRANSPORT_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */
+#endif /* TRANSPORT_ALTCP */
+#endif /* TRANSPORT_HDR_ALTCP_MBEDTLS_MEM_H */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls_mbedtls_opts.h b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls_mbedtls_opts.h
new file mode 100644
index 00000000000000..6bc85d7107fbc5
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls_mbedtls_opts.h
@@ -0,0 +1,67 @@
+/**
+ * @file
+ * Application layered TCP/TLS connection API (to be used from TCPIP thread)
+ *
+ * This file contains options for an mbedtls port of the TLS layer.
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+#ifndef TRANSPORT_HDR_ALTCP_TLS_OPTS_H
+#define TRANSPORT_HDR_ALTCP_TLS_OPTS_H
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+/** LWIP_ALTCP_TLS_MBEDTLS==1: use mbedTLS for TLS support for altcp API
+ * mbedtls include directory must be reachable via include search path
+ */
+#ifndef TRANSPORT_ALTCP_TLS_MBEDTLS
+#define TRANSPORT_ALTCP_TLS_MBEDTLS 0
+#endif
+
+/** Configure debug level of this file */
+#ifndef ALTCP_MBEDTLS_DEBUG
+#define ALTCP_MBEDTLS_DEBUG 0
+#endif
+
+/** Set a session timeout in seconds for the basic session cache
+ * ATTENTION: Using a session cache can lower security by reusing keys!
+ */
+#ifndef ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS
+#define ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS 0
+#endif
+
+#endif /* TRANSPORT_ALTCP */
+
+#endif /* TRANSPORT_HDR_ALTCP_TLS_OPTS_H */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls_mbedtls_structs.h b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls_mbedtls_structs.h
new file mode 100644
index 00000000000000..ffbd2612cbed9e
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/include/altcp_tls_mbedtls_structs.h
@@ -0,0 +1,83 @@
+/**
+ * @file
+ * Application layered TCP/TLS connection API (to be used from TCPIP thread)
+ *
+ * This file contains structure definitions for a TLS layer using mbedTLS.
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+#ifndef TRANSPORT_HDR_ALTCP_MBEDTLS_STRUCTS_H
+#define TRANSPORT_HDR_ALTCP_MBEDTLS_STRUCTS_H
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#include "altcp_tls_mbedtls_opts.h"
+
+#if TRANSPORT_ALTCP_TLS && TRANSPORT_ALTCP_TLS_MBEDTLS
+
+#include "altcp.h"
+#include "lwip/pbuf.h"
+
+#include "mbedtls/ssl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE 0x01
+#define ALTCP_MBEDTLS_FLAGS_UPPER_CALLED 0x02
+#define ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED 0x04
+#define ALTCP_MBEDTLS_FLAGS_RX_CLOSED 0x08
+#define ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT 0x10
+
+typedef struct altcp_mbedtls_state_s {
+ void *conf;
+ mbedtls_ssl_context ssl_context;
+ /* chain of rx pbufs (before decryption) */
+ struct pbuf *rx;
+ struct pbuf *rx_app;
+ u8_t flags;
+ int rx_passed_unrecved;
+ int bio_bytes_read;
+ int bio_bytes_appl;
+} altcp_mbedtls_state_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TRANSPORT_ALTCP_TLS && TRANSPORT_ALTCP_TLS_MBEDTLS */
+#endif /* TRANSPORT_ALTCP */
+#endif /* TRANSPORT_HDR_ALTCP_MBEDTLS_STRUCTS_H */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/include/tcpbase.h b/third_party/silabs/mqtt/mqtt_transport_interface/include/tcpbase.h
new file mode 100644
index 00000000000000..e8fb8d9694cd87
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/include/tcpbase.h
@@ -0,0 +1,89 @@
+/**
+ * @file
+ * Base TCP API definitions shared by TCP and ALTCP\n
+ * See also @ref tcp_raw
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels
+ *
+ */
+#ifndef LWIP_HDR_TCPBASE_H
+#define LWIP_HDR_TCPBASE_H
+
+#include "lwip/opt.h"
+#include "lwip/tcp.h"
+
+#if TRANSPORT_TCP /* don't build if not configured for use in lwipopts.h */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if LWIP_WND_SCALE
+typedef u32_t tcpwnd_size_t;
+#else
+typedef u16_t tcpwnd_size_t;
+#endif
+
+enum tcp_state {
+ CLOSED = 0,
+ LISTEN = 1,
+ SYN_SENT = 2,
+ SYN_RCVD = 3,
+ ESTABLISHED = 4,
+ FIN_WAIT_1 = 5,
+ FIN_WAIT_2 = 6,
+ CLOSE_WAIT = 7,
+ CLOSING = 8,
+ LAST_ACK = 9,
+ TIME_WAIT = 10
+};
+/* ATTENTION: this depends on state number ordering! */
+#define TCP_STATE_IS_CLOSING(state) ((state) >= FIN_WAIT_1)
+
+/* Flags for "apiflags" parameter in tcp_write */
+#define TCP_WRITE_FLAG_COPY 0x01
+#define TCP_WRITE_FLAG_MORE 0x02
+
+#define TCP_PRIO_MIN 1
+#define TCP_PRIO_NORMAL 64
+#define TCP_PRIO_MAX 127
+
+const char* tcp_debug_state_str(enum tcp_state s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TRANSPORT_TCP */
+
+#endif /* TRANSPORT_HDR_TCPBASE_H */
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/src/MQTT_transport.c b/third_party/silabs/mqtt/mqtt_transport_interface/src/MQTT_transport.c
new file mode 100644
index 00000000000000..5ac065e6d9f615
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/src/MQTT_transport.c
@@ -0,0 +1,431 @@
+/*
+ *
+ * Copyright (c) 2023 Project CHIP Authors
+ * Copyright (c) 2022 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 "MQTT_transport.h"
+#include
+#ifdef SIWX_917
+#include "siwx917_utils.h"
+#else
+#include "efr32_utils.h"
+#endif
+#include "lwip/timeouts.h"
+#include "lwip/dns.h"
+#include "altcp.h"
+#include "altcp_tcp.h"
+
+struct MQTT_Transport_t
+{
+ u8_t conn_state;
+ struct altcp_tls_config *tls_config;
+ struct altcp_pcb *conn;
+
+ dic_connect_cb dic_conn_cb;
+ ip_addr_t *ipaddr;
+ /** received buffers from tcp */
+ struct pbuf *pcbRxStart;
+ struct pbuf *pcbRxEnd;
+
+ SemaphoreHandle_t sync_sem;
+ /* Temp */
+ EventGroupHandle_t events;
+};
+
+enum{
+ TRANSPORT_NOT_CONNECTED,
+ TRANSPORT_CONNECTED,
+};
+
+static void setup_transport_callbacks(MQTT_Transport_t *client, mqtt_transport_intf_t *trans);
+static err_t connection_new(MQTT_Transport_t* , const ip_addr_t *ipaddr, u16_t port);
+uint8_t convert_write_flags(uint8_t apiflag);
+
+inline uint8_t convert_write_flags(uint8_t apiflag){
+ uint8_t transport_flag=0;
+ if(apiflag & MQTT_WRITE_FLAG_COPY){
+ transport_flag |= TCP_WRITE_FLAG_COPY;
+ }
+ if(apiflag & MQTT_WRITE_FLAG_MORE){
+ transport_flag |= TCP_WRITE_FLAG_MORE;
+ }
+ return transport_flag;
+}
+
+void dns_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg){
+ SILABS_LOG("DNS CALL BACK");
+ MQTT_Transport_t* transP = (MQTT_Transport_t* )callback_arg;
+ memcpy(transP->ipaddr, ipaddr, sizeof(ip_addr_t));
+ xSemaphoreGive(transP->sync_sem);
+ return;
+}
+
+MQTT_Transport_t * MQTT_Transport_Init(mqtt_transport_intf_t *trans,mqtt_client_t* mqtt_client,EventGroupHandle_t dicEvents)
+{
+ if(trans == NULL && mqtt_client == NULL && dicEvents == NULL){
+ SILABS_LOG("MQTT transport init failed");
+ return NULL;
+ }
+ MQTT_Transport_t *client = (MQTT_Transport_t *)pvPortMalloc(sizeof(MQTT_Transport_t));
+ if (client != NULL) {
+ SILABS_LOG("dns_servers[0] = %s\n", ipaddr_ntoa(dns_getserver(0)));
+ memset(client, 0, sizeof(MQTT_Transport_t));
+ setup_transport_callbacks(client, trans);
+ client->events = dicEvents;
+ }
+ return client;
+}
+
+err_t MQTT_Transport_SSLConfigure(MQTT_Transport_t *transP, const u8_t *ca, size_t ca_len, const u8_t *privkey, size_t privkey_len,
+ const u8_t *privkey_pass, size_t privkey_pass_len,
+ const u8_t *cert, size_t cert_len)
+{
+ struct altcp_tls_config *altcp_tls_config;
+ altcp_tls_config = altcp_tls_create_config_client_2wayauth(ca,ca_len,privkey,privkey_len,NULL,0,cert,cert_len);
+ if (NULL == altcp_tls_config)
+ {
+ return ERR_FAIL;
+ }
+ transP->tls_config = altcp_tls_config;
+ return ERR_OK;
+}
+
+err_t MQTT_Transport_Connect(MQTT_Transport_t* transP,const char *host, u16_t port, dic_connect_cb dic_conn_cb)
+{
+ err_t ret;
+ err_t dns_ret;
+ ip_addr_t ipaddr;
+ if(transP == NULL && host == NULL){
+ SILABS_LOG("MQTT transport connect failed");
+ return ERR_ARG;
+ }
+ transP->sync_sem = xSemaphoreCreateCounting(1, 0);
+ transP->ipaddr = &ipaddr;
+ if((dns_ret = dns_gethostbyname(host,&ipaddr,dns_callback,transP)) != ERR_OK) {
+ if(dns_ret == ERR_INPROGRESS){
+ SILABS_LOG("in progress");
+ xSemaphoreTake(transP->sync_sem, portMAX_DELAY);
+ }
+ else {
+ SILABS_LOG("dns resolving failed %d",dns_ret);
+ return dns_ret;
+ }
+ }
+ transP->dic_conn_cb = dic_conn_cb;
+ ret = connection_new(transP,&ipaddr,port);
+ return ret;
+}
+
+static uint16_t transport_get_sendlen_cb(void *conn)
+{
+ MQTT_Transport_t *client = (MQTT_Transport_t*)conn;
+ if (!client) return 0;
+ return altcp_sndbuf(client->conn);
+}
+
+static int8_t transport_write_cb(void *conn, void *buff, uint16_t len, uint8_t flags, uint8_t isFinal)
+{
+ MQTT_Transport_t *client = (MQTT_Transport_t*)conn;
+ if (!client) return ERR_FAIL;
+ if (ERR_OK != altcp_write(client->conn, buff, len, convert_write_flags(flags)))
+ return ERR_FAIL;
+ if (isFinal)
+ altcp_output(client->conn);
+ return ERR_OK;
+}
+
+static uint16_t transport_get_recvlen_cb(void *conn)
+{
+ MQTT_Transport_t *client = (MQTT_Transport_t*)conn;
+ if (!client) return 0;
+ if (!client->pcbRxStart) return 0;
+ return client->pcbRxStart->tot_len;
+}
+
+static int8_t transport_recv_from_nw(void *conn, void *buf, uint16_t len, uint16_t offset)
+{
+ MQTT_Transport_t *client = (MQTT_Transport_t*)conn;
+ struct pbuf *curr = client->pcbRxStart, *next;
+ uint16_t slen;
+ if (!client) return 0;
+ if (!client->pcbRxStart) return 0;
+ if (client->pcbRxStart->tot_len < (offset + len)) return 0;
+ pbuf_copy_partial(curr, buf, len, offset);
+ if (offset + len >= curr->tot_len)
+ {
+ slen=curr->len;
+ while (slen < client->pcbRxStart->tot_len)
+ {
+ curr=curr->next;
+ slen+= curr->len;
+ }
+ next = curr->next;
+ curr->next = NULL;
+ pbuf_free(client->pcbRxStart);
+ client->pcbRxStart=next;
+ }
+ return len;
+}
+
+static void
+transport_close_cb(void *arg){
+ MQTT_Transport_t *client = (MQTT_Transport_t *)arg;
+ struct altcp_pcb *conn = client->conn;
+ /* Bring down TCP connection if not already done */
+ if (conn != NULL && client->conn_state == TRANSPORT_CONNECTED) {
+ err_t res;
+ altcp_recv(conn, NULL);
+ altcp_err(conn, NULL);
+ altcp_sent(conn, NULL);
+ res = altcp_close(conn);
+ if (res != ERR_OK) {
+ altcp_abort(conn);
+ TRANSPORT_DEBUGF(("transport_close_cb: Close err=%s\n", lwip_strerr(res)));
+ }
+ client->conn = NULL;
+ }
+}
+
+static void transport_timerStart(u32_t msecs, timer_callback handler, void *arg)
+{
+ sys_timeout(msecs, (sys_timeout_handler)handler, arg);
+}
+
+static void transport_timerStop(timer_callback handler, void *arg)
+{
+ sys_untimeout((sys_timeout_handler)handler, arg);
+}
+
+/**
+ * TCP error callback function. @see tcp_err_fn
+ * @param arg MQTT client
+ * @param err Error encountered
+ */
+
+static void
+transport_err_cb(void *arg, err_t err)
+{
+ MQTT_Transport_t *client = (MQTT_Transport_t *)arg;
+ TRANSPORT_UNUSED_ARG(err); /* only used for debug output */
+ TRANSPORT_DEBUGF(("transport_err_cb: TCP error callback: error %d, arg: %p\n", err, arg));
+ TRANSPORT_ASSERT("transport_err_cb: client != NULL", client != NULL);
+ /* Set conn to null before calling close as pcb is already deallocated*/
+ if (client->conn_state)
+ xEventGroupSetBits(client->events, SIGNAL_TRANSINTF_CONN_CLOSE);
+ client->conn_state = TRANSPORT_NOT_CONNECTED;
+ client->dic_conn_cb(err);
+}
+
+static err_t
+transport_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err)
+{
+ MQTT_Transport_t *client = (MQTT_Transport_t *)arg;
+ TRANSPORT_ASSERT("transport_recv_cb: client != NULL", client != NULL);
+ TRANSPORT_ASSERT("transport_recv_cb: client->conn == pcb", client->conn == pcb);
+
+ if (p == NULL) {
+ TRANSPORT_DEBUGF(("transport_recv_cb: Recv pbuf=NULL, remote has closed connection\n"));
+ xEventGroupSetBits(client->events, SIGNAL_TRANSINTF_CONN_CLOSE);
+ } else {
+ if (err != ERR_OK) {
+ TRANSPORT_DEBUGF(("transport_recv_cb: Recv err=%d\n", err));
+ pbuf_free(p);
+ return err;
+ }
+
+#if 0
+ /* Tell remote that data has been received */
+ altcp_recved(pcb, p->tot_len);
+ res = mqtt_parse_incoming(client, p);
+ pbuf_free(p);
+
+ if (res != MQTT_CONNECT_ACCEPTED) {
+ mqtt_close(client, res);
+ }
+ //#endif
+ /* If keep alive functionality is used */
+ if (client->keep_alive != 0) {
+ /* Reset server alive watchdog */
+ client->server_watchdog = 0;
+ }
+#else
+ if (client->pcbRxStart == NULL) {
+ client->pcbRxStart = p;
+ while (p->next) p = p->next;
+ client->pcbRxEnd = p;
+ }
+ else
+ {
+ client->pcbRxEnd->next = p;
+ client->pcbRxEnd = p;
+ }
+ xEventGroupSetBits(client->events, SIGNAL_TRANSINTF_RX);
+#endif
+}
+ return ERR_OK;
+}
+
+/**
+ * TCP data sent callback function. @see tcp_sent_fn
+ * @param arg MQTT client
+ * @param tpcb TCP connection handle
+ * @param len Number of bytes sent
+ * @return ERR_OK
+ */
+
+static err_t
+transport_sent_cb(void *arg, struct altcp_pcb *tpcb, u16_t len)
+{
+ MQTT_Transport_t *client = (MQTT_Transport_t *)arg;
+ TRANSPORT_ASSERT("transport_recv_cb: client != NULL", client != NULL);
+ TRANSPORT_UNUSED_ARG(tpcb);
+ TRANSPORT_UNUSED_ARG(len);
+ if (client->conn_state == TRANSPORT_CONNECTED) {
+ xEventGroupSetBits(client->events, SIGNAL_TRANSINTF_TX_ACK);
+ }
+ return ERR_OK;
+}
+
+#if 0 //future use
+/**
+ * TCP poll callback function. @see tcp_poll_fn
+ * @param arg MQTT client
+ * @param tpcb TCP connection handle
+ * @return err ERR_OK
+ */
+static err_t
+transport_poll_cb(void *arg, struct tcp_pcb *tpcb)
+{
+ // MQTT_Transport_t *tclient = (MQTT_Transport_t *)arg;
+ // mqtt_client_t *client = (mqtt_client_t *)tclient->appHdl;
+ // if (client->conn_state == TRANSPORT_CONNECTED) {
+ MQTT_Transport_t *client = (MQTT_Transport_t *)arg;
+ if (client->conn_state == TRANSPORT_CONNECTED) {
+ /* Try send any remaining buffers from output queue */
+ mqtt_output_send(&client->output, tpcb);
+ }
+ return ERR_OK;
+}
+#endif
+
+/**
+ * TCP connect callback function. @see tcp_connected_fn
+ * @param arg MQTT client
+ * @param err Always ERR_OK, transport_err_cb is called in case of error
+ * @return ERR_OK
+ */
+
+static err_t
+transport_connect_cb(void *arg, struct altcp_pcb *tpcb, err_t err)
+{
+ MQTT_Transport_t* client = (MQTT_Transport_t *)arg;
+ if (err != ERR_OK) {
+ TRANSPORT_DEBUGF(("transport_connect_cb: TCP connect error %d\n", err));
+ SILABS_LOG("TCP connect error");
+ client->conn_state = TRANSPORT_NOT_CONNECTED;
+ client->dic_conn_cb(err);
+ return err;
+ }
+ /* Setup TCP callbacks */
+ altcp_recv(tpcb, transport_recv_cb);
+ altcp_sent(tpcb, transport_sent_cb);
+ //tcp_poll(tpcb, tcp_poll_cb, 2);
+ TRANSPORT_DEBUGF(("transport_connect_cb: TCP connection established to server\n"));
+ SILABS_LOG("tcp_cb: TCP connection established to server\n");
+ client->conn_state = TRANSPORT_CONNECTED;
+ if(client->dic_conn_cb != NULL){
+ client->dic_conn_cb(ERR_OK);
+ }
+ return ERR_OK;
+}
+
+void mbedtls_signal_app(void *arg)
+{
+ MQTT_Transport_t *client = (MQTT_Transport_t *)arg;
+ xEventGroupSetBits(client->events, SIGNAL_TRANSINTF_MBEDTLS_RX);
+}
+extern err_t
+altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn);
+
+void transport_process_mbedtls_rx(MQTT_Transport_t *client)
+{
+ altcp_mbedtls_lower_recv_process(client->conn);
+}
+
+static err_t connection_new(MQTT_Transport_t* client , const ip_addr_t *ipaddr, u16_t port)
+{
+ err_t err = ERR_ABRT;
+ if(client == NULL || ipaddr == NULL) {
+ SILABS_LOG("NULL argments");
+ return ERR_VAL;
+ }
+ if (client->conn != NULL) {
+ SILABS_LOG("connection already established");
+ return ERR_ISCONN;
+ }
+
+#if TRANSPORT_ALTCP && TRANSPORT_ALTCP_TLS
+ if (client->tls_config) {
+ SILABS_LOG("executing tls new");
+ client->conn = altcp_tls_new(client->tls_config, IP_GET_TYPE(ipaddr));
+ } else
+#endif
+ {
+ SILABS_LOG("not executing");
+ client->conn = altcp_tcp_new_ip_type(IP_GET_TYPE(ipaddr));
+ }
+ if (client->conn == NULL) {
+ return ERR_MEM;
+ }
+ /* Set arg pointer for callbacks */
+ altcp_arg(client->conn, client);
+ /* Any local address, pick random local port number */
+ err = altcp_bind(client->conn, IP_ADDR_ANY, 0);
+ if (err != ERR_OK) {
+ TRANSPORT_DEBUGF(("client_connect: Error binding to local ip/port, %d\n", err));
+ goto transport_fail;
+ }
+
+ /* Connect to server */
+ err = altcp_connect(client->conn, ipaddr, port, transport_connect_cb);
+ if (err != ERR_OK) {
+ TRANSPORT_DEBUGF(("client_connect: Error connecting to remote ip/port, %d\n", err));
+ goto transport_fail;
+ }
+ /* Set error callback */
+ altcp_err(client->conn, transport_err_cb);
+ client->conn_state = TRANSPORT_NOT_CONNECTED;
+
+ return ERR_OK;
+
+transport_fail:
+ altcp_abort(client->conn);
+ client->conn = NULL;
+ return err;
+}
+
+static void setup_transport_callbacks(MQTT_Transport_t *client, mqtt_transport_intf_t *trans)
+{
+ trans->connCtxt = client;
+ trans->get_send_len = transport_get_sendlen_cb;
+ trans->send_to_network = transport_write_cb;
+ trans->get_recv_len = transport_get_recvlen_cb;
+ trans->recv_from_network = transport_recv_from_nw;
+ trans->close_connection = transport_close_cb;
+ trans->timer_start = transport_timerStart;
+ trans->timer_stop = transport_timerStop;
+}
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp.c b/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp.c
new file mode 100644
index 00000000000000..9107ca166b42c7
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp.c
@@ -0,0 +1,681 @@
+/**
+ * @file
+ * @defgroup altcp Application layered TCP Functions
+ * @ingroup altcp_api
+ *
+ * This file contains the common functions for altcp to work.
+ * For more details see @ref altcp_api.
+ */
+
+/**
+ * @defgroup altcp_api Application layered TCP Introduction
+ * @ingroup callbackstyle_api
+ *
+ * Overview
+ * --------
+ * altcp (application layered TCP connection API; to be used from TCPIP thread)
+ * is an abstraction layer that prevents applications linking hard against the
+ * @ref tcp.h functions while providing the same functionality. It is used to
+ * e.g. add SSL/TLS (see LWIP_ALTCP_TLS) or proxy-connect support to an application
+ * written for the tcp callback API without that application knowing the
+ * protocol details.
+ *
+ * * This interface mimics the tcp callback API to the application while preventing
+ * direct linking (much like virtual functions).
+ * * This way, an application can make use of other application layer protocols
+ * on top of TCP without knowing the details (e.g. TLS, proxy connection).
+ * * This is achieved by simply including "lwip/altcp.h" instead of "lwip/tcp.h",
+ * replacing "struct tcp_pcb" with "struct altcp_pcb" and prefixing all functions
+ * with "altcp_" instead of "tcp_".
+ *
+ * With altcp support disabled (LWIP_ALTCP==0), applications written against the
+ * altcp API can still be compiled but are directly linked against the tcp.h
+ * callback API and then cannot use layered protocols. To minimize code changes
+ * in this case, the use of altcp_allocators is strongly suggested.
+ *
+ * Usage
+ * -----
+ * To make use of this API from an existing tcp raw API application:
+ * * Include "lwip/altcp.h" instead of "lwip/tcp.h"
+ * * Replace "struct tcp_pcb" with "struct altcp_pcb"
+ * * Prefix all called tcp API functions with "altcp_" instead of "tcp_" to link
+ * against the altcp functions
+ * * @ref altcp_new (and @ref altcp_new_ip_type/@ref altcp_new_ip6) take
+ * an @ref altcp_allocator_t as an argument, whereas the original tcp API
+ * functions take no arguments.
+ * * An @ref altcp_allocator_t allocator is an object that holds a pointer to an
+ * allocator object and a corresponding state (e.g. for TLS, the corresponding
+ * state may hold certificates or keys). This way, the application does not
+ * even need to know if it uses TLS or pure TCP, this is handled at runtime
+ * by passing a specific allocator.
+ * * An application can alternatively bind hard to the altcp_tls API by calling
+ * @ref altcp_tls_new or @ref altcp_tls_wrap.
+ * * The TLS layer is not directly implemented by lwIP, but a port to mbedTLS is
+ * provided.
+ * * Another altcp layer is proxy-connect to use TLS behind a HTTP proxy (see
+ * @ref altcp_proxyconnect.h)
+ *
+ * altcp_allocator_t
+ * -----------------
+ * An altcp allocator is created by the application by combining an allocator
+ * callback function and a corresponding state, e.g.:\code{.c}
+ * static const unsigned char cert[] = {0x2D, ... (see mbedTLS doc for how to create this)};
+ * struct altcp_tls_config * conf = altcp_tls_create_config_client(cert, sizeof(cert));
+ * altcp_allocator_t tls_allocator = {
+ * altcp_tls_alloc, conf
+ * };
+ * \endcode
+ *
+ *
+ * struct altcp_tls_config
+ * -----------------------
+ * The struct altcp_tls_config holds state that is needed to create new TLS client
+ * or server connections (e.g. certificates and private keys).
+ *
+ * It is not defined by lwIP itself but by the TLS port (e.g. altcp_tls to mbedTLS
+ * adaption). However, the parameters used to create it are defined in @ref
+ * altcp_tls.h (see @ref altcp_tls_create_config_server_privkey_cert for servers
+ * and @ref altcp_tls_create_config_client/@ref altcp_tls_create_config_client_2wayauth
+ * for clients).
+ *
+ * For mbedTLS, ensure that certificates can be parsed by 'mbedtls_x509_crt_parse()' and
+ * private keys can be parsed by 'mbedtls_pk_parse_key()'.
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#include "altcp.h"
+#include "altcp_priv.h"
+#include "altcp_tcp.h"
+#include "lwip/tcp.h"
+#include "altcp_tls_mbedtls_structs.h"
+
+#include
+
+extern const struct altcp_functions altcp_tcp_functions;
+
+/**
+ * For altcp layer implementations only: allocate a new struct altcp_pcb from the pool
+ * and zero the memory
+ */
+struct altcp_pcb *
+altcp_alloc(void)
+{
+ struct altcp_pcb *ret = (struct altcp_pcb *)pvPortMalloc(sizeof(struct altcp_pcb));
+ if (ret != NULL) {
+ memset(ret, 0, sizeof(struct altcp_pcb));
+ }
+ return ret;
+}
+
+/**
+ * For altcp layer implementations only: return a struct altcp_pcb to the pool
+ */
+void
+altcp_free(struct altcp_pcb *conn)
+{
+ if (conn) {
+ if (conn->fns && conn->fns->dealloc) {
+ conn->fns->dealloc(conn);
+ }
+ vPortFree(conn);
+ }
+}
+
+/**
+ * @ingroup altcp
+ * altcp_new_ip6: @ref altcp_new for IPv6
+ */
+struct altcp_pcb *
+altcp_new_ip6(altcp_allocator_t *allocator)
+{
+ return altcp_new_ip_type(allocator, IPADDR_TYPE_V6);
+}
+
+/**
+ * @ingroup altcp
+ * altcp_new: @ref altcp_new for IPv4
+ */
+struct altcp_pcb *
+altcp_new(altcp_allocator_t *allocator)
+{
+ return altcp_new_ip_type(allocator, IPADDR_TYPE_V4);
+}
+
+/**
+ * @ingroup altcp
+ * altcp_new_ip_type: called by applications to allocate a new pcb with the help of an
+ * allocator function.
+ *
+ * @param allocator allocator function and argument
+ * @param ip_type IP version of the pcb (@ref lwip_ip_addr_type)
+ * @return a new altcp_pcb or NULL on error
+ */
+struct altcp_pcb *
+altcp_new_ip_type(altcp_allocator_t *allocator, u8_t ip_type)
+{
+ struct altcp_pcb *conn;
+ if (allocator == NULL) {
+ /* no allocator given, create a simple TCP connection */
+ return altcp_tcp_new_ip_type(ip_type);
+ }
+ if (allocator->alloc == NULL) {
+ /* illegal allocator */
+ return NULL;
+ }
+ conn = allocator->alloc(allocator->arg, ip_type);
+ if (conn == NULL) {
+ /* allocation failed */
+ return NULL;
+ }
+ return conn;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_arg()
+ */
+void
+altcp_arg(struct altcp_pcb *conn, void *arg)
+{
+ if (conn) {
+ conn->arg = arg;
+ }
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_accept()
+ */
+void
+altcp_accept(struct altcp_pcb *conn, altcp_accept_fn accept)
+{
+ if (conn != NULL) {
+ conn->accept = accept;
+ }
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_recv()
+ */
+void
+altcp_recv(struct altcp_pcb *conn, altcp_recv_fn recv)
+{
+ if (conn) {
+ conn->recv = recv;
+ }
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_sent()
+ */
+void
+altcp_sent(struct altcp_pcb *conn, altcp_sent_fn sent)
+{
+ if (conn) {
+ conn->sent = sent;
+ }
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_poll()
+ */
+void
+altcp_poll(struct altcp_pcb *conn, altcp_poll_fn poll, u8_t interval)
+{
+ if (conn) {
+ conn->poll = poll;
+ conn->pollinterval = interval;
+ if (conn->fns && conn->fns->set_poll) {
+ conn->fns->set_poll(conn, interval);
+ }
+ }
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_err()
+ */
+void
+altcp_err(struct altcp_pcb *conn, altcp_err_fn err)
+{
+ if (conn) {
+ conn->err = err;
+ }
+}
+
+/* Generic functions calling the "virtual" ones */
+
+/**
+ * @ingroup altcp
+ * @see tcp_recved()
+ */
+void
+altcp_recved(struct altcp_pcb *conn, u16_t len)
+{
+ if (conn && conn->fns && conn->fns->recved) {
+ conn->fns->recved(conn, len);
+ }
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_bind()
+ */
+err_t
+altcp_bind(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port)
+{
+ if (conn && conn->fns && conn->fns->bind) {
+ return conn->fns->bind(conn, ipaddr, port);
+ }
+ return ERR_VAL;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_connect()
+ */
+err_t
+altcp_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected)
+{
+ if (conn && conn->fns && conn->fns->connect) {
+ return conn->fns->connect(conn, ipaddr, port, connected);
+ }
+ return ERR_VAL;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_listen_with_backlog_and_err()
+ */
+struct altcp_pcb *
+altcp_listen_with_backlog_and_err(struct altcp_pcb *conn, u8_t backlog, err_t *err)
+{
+ if (conn && conn->fns && conn->fns->listen) {
+ return conn->fns->listen(conn, backlog, err);
+ }
+ return NULL;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_abort()
+ */
+void
+altcp_abort(struct altcp_pcb *conn)
+{
+ if (conn && conn->fns && conn->fns->abort) {
+ conn->fns->abort(conn);
+ }
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_close()
+ */
+err_t
+altcp_close(struct altcp_pcb *conn)
+{
+ if (conn && conn->fns && conn->fns->close) {
+ return conn->fns->close(conn);
+ }
+ return ERR_VAL;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_shutdown()
+ */
+err_t
+altcp_shutdown(struct altcp_pcb *conn, int shut_rx, int shut_tx)
+{
+ if (conn && conn->fns && conn->fns->shutdown) {
+ return conn->fns->shutdown(conn, shut_rx, shut_tx);
+ }
+ return ERR_VAL;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_write()
+ */
+err_t
+altcp_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags)
+{
+ if (conn && conn->fns && conn->fns->write) {
+ return conn->fns->write(conn, dataptr, len, apiflags);
+ }
+ return ERR_VAL;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_output()
+ */
+err_t
+altcp_output(struct altcp_pcb *conn)
+{
+ if (conn && conn->fns && conn->fns->output) {
+ return conn->fns->output(conn);
+ }
+ return ERR_VAL;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_mss()
+ */
+u16_t
+altcp_mss(struct altcp_pcb *conn)
+{
+ if (conn && conn->fns && conn->fns->mss) {
+ return conn->fns->mss(conn);
+ }
+ return 0;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_sndbuf()
+ */
+u16_t
+altcp_sndbuf(struct altcp_pcb *conn)
+{
+ if (conn && conn->fns && conn->fns->sndbuf) {
+ return conn->fns->sndbuf(conn);
+ }
+ return 0;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_sndqueuelen()
+ */
+u16_t
+altcp_sndqueuelen(struct altcp_pcb *conn)
+{
+ if (conn && conn->fns && conn->fns->sndqueuelen) {
+ return conn->fns->sndqueuelen(conn);
+ }
+ return 0;
+}
+
+void
+altcp_nagle_disable(struct altcp_pcb *conn)
+{
+ if (conn && conn->fns && conn->fns->nagle_disable) {
+ conn->fns->nagle_disable(conn);
+ }
+}
+
+void
+altcp_nagle_enable(struct altcp_pcb *conn)
+{
+ if (conn && conn->fns && conn->fns->nagle_enable) {
+ conn->fns->nagle_enable(conn);
+ }
+}
+
+int
+altcp_nagle_disabled(struct altcp_pcb *conn)
+{
+ if (conn && conn->fns && conn->fns->nagle_disabled) {
+ return conn->fns->nagle_disabled(conn);
+ }
+ return 0;
+}
+
+/**
+ * @ingroup altcp
+ * @see tcp_setprio()
+ */
+void
+altcp_setprio(struct altcp_pcb *conn, u8_t prio)
+{
+ if (conn && conn->fns && conn->fns->setprio) {
+ conn->fns->setprio(conn, prio);
+ }
+}
+
+err_t
+altcp_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port)
+{
+ if (conn && conn->fns && conn->fns->addrinfo) {
+ return conn->fns->addrinfo(conn, local, addr, port);
+ }
+ return ERR_VAL;
+}
+
+ip_addr_t *
+altcp_get_ip(struct altcp_pcb *conn, int local)
+{
+ if (conn && conn->fns && conn->fns->getip) {
+ return conn->fns->getip(conn, local);
+ }
+ return NULL;
+}
+
+u16_t
+altcp_get_port(struct altcp_pcb *conn, int local)
+{
+ if (conn && conn->fns && conn->fns->getport) {
+ return conn->fns->getport(conn, local);
+ }
+ return 0;
+}
+
+#ifdef ALTCP_DEBUG
+enum tcp_state
+altcp_dbg_get_tcp_state(struct altcp_pcb *conn)
+{
+ if (conn && conn->fns && conn->fns->dbg_get_tcp_state) {
+ return conn->fns->dbg_get_tcp_state(conn);
+ }
+ return CLOSED;
+}
+#endif
+
+/* Default implementations for the "virtual" functions */
+
+void
+altcp_default_set_poll(struct altcp_pcb *conn, u8_t interval)
+{
+ if (conn && conn->inner_conn) {
+ altcp_poll(conn->inner_conn, conn->poll, interval);
+ }
+}
+
+void
+altcp_default_recved(struct altcp_pcb *conn, u16_t len)
+{
+ if (conn && conn->inner_conn) {
+ altcp_recved(conn->inner_conn, len);
+ }
+}
+
+err_t
+altcp_default_bind(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_bind(conn->inner_conn, ipaddr, port);
+ }
+ return ERR_VAL;
+}
+
+err_t
+altcp_default_shutdown(struct altcp_pcb *conn, int shut_rx, int shut_tx)
+{
+ if (conn) {
+ if (shut_rx && shut_tx && conn->fns && conn->fns->close) {
+ /* default shutdown for both sides is close */
+ return conn->fns->close(conn);
+ }
+ if (conn->inner_conn) {
+ return altcp_shutdown(conn->inner_conn, shut_rx, shut_tx);
+ }
+ }
+ return ERR_VAL;
+}
+
+err_t
+altcp_default_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_write(conn->inner_conn, dataptr, len, apiflags);
+ }
+ return ERR_VAL;
+}
+
+err_t
+altcp_default_output(struct altcp_pcb *conn)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_output(conn->inner_conn);
+ }
+ return ERR_VAL;
+}
+
+u16_t
+altcp_default_mss(struct altcp_pcb *conn)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_mss(conn->inner_conn);
+ }
+ return 0;
+}
+
+u16_t
+altcp_default_sndbuf(struct altcp_pcb *conn)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_sndbuf(conn->inner_conn);
+ }
+ return 0;
+}
+
+u16_t
+altcp_default_sndqueuelen(struct altcp_pcb *conn)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_sndqueuelen(conn->inner_conn);
+ }
+ return 0;
+}
+
+void
+altcp_default_nagle_disable(struct altcp_pcb *conn)
+{
+ if (conn && conn->inner_conn) {
+ altcp_nagle_disable(conn->inner_conn);
+ }
+}
+
+void
+altcp_default_nagle_enable(struct altcp_pcb *conn)
+{
+ if (conn && conn->inner_conn) {
+ altcp_nagle_enable(conn->inner_conn);
+ }
+}
+
+int
+altcp_default_nagle_disabled(struct altcp_pcb *conn)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_nagle_disabled(conn->inner_conn);
+ }
+ return 0;
+}
+
+void
+altcp_default_setprio(struct altcp_pcb *conn, u8_t prio)
+{
+ if (conn && conn->inner_conn) {
+ altcp_setprio(conn->inner_conn, prio);
+ }
+}
+
+void
+altcp_default_dealloc(struct altcp_pcb *conn)
+{
+ TRANSPORT_UNUSED_ARG(conn);
+ /* nothing to do */
+}
+
+err_t
+altcp_default_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_get_tcp_addrinfo(conn->inner_conn, local, addr, port);
+ }
+ return ERR_VAL;
+}
+
+ip_addr_t *
+altcp_default_get_ip(struct altcp_pcb *conn, int local)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_get_ip(conn->inner_conn, local);
+ }
+ return NULL;
+}
+
+u16_t
+altcp_default_get_port(struct altcp_pcb *conn, int local)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_get_port(conn->inner_conn, local);
+ }
+ return 0;
+}
+
+#ifdef ALTCP_DEBUG
+enum tcp_state
+altcp_default_dbg_get_tcp_state(struct altcp_pcb *conn)
+{
+ if (conn && conn->inner_conn) {
+ return altcp_dbg_get_tcp_state(conn->inner_conn);
+ }
+ return CLOSED;
+}
+#endif
+
+
+#endif /* TRANSPORT_ALTCP */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_alloc.c b/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_alloc.c
new file mode 100644
index 00000000000000..d9bce4157f9806
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_alloc.c
@@ -0,0 +1,86 @@
+/**
+ * @file
+ * Application layered TCP connection API (to be used from TCPIP thread)\n
+ * This interface mimics the tcp callback API to the application while preventing
+ * direct linking (much like virtual functions).
+ * This way, an application can make use of other application layer protocols
+ * on top of TCP without knowing the details (e.g. TLS, proxy connection).
+ *
+ * This file contains allocation implementation that combine several layers.
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#include "altcp.h"
+#include "altcp_tcp.h"
+#include "altcp_tls.h"
+#include "altcp_priv.h"
+
+#include
+
+#if TRANSPORT_ALTCP_TLS
+
+/** This standard allocator function creates an altcp pcb for
+ * TLS over TCP */
+struct altcp_pcb *
+altcp_tls_new(struct altcp_tls_config *config, u8_t ip_type)
+{
+ struct altcp_pcb *inner_conn, *ret;
+ TRANSPORT_UNUSED_ARG(ip_type);
+
+ inner_conn = altcp_tcp_new_ip_type(ip_type);
+ if (inner_conn == NULL) {
+ return NULL;
+ }
+ ret = altcp_tls_wrap(config, inner_conn);
+ if (ret == NULL) {
+ altcp_close(inner_conn);
+ }
+ return ret;
+}
+
+/** This standard allocator function creates an altcp pcb for
+ * TLS over TCP */
+struct altcp_pcb *
+altcp_tls_alloc(void *arg, u8_t ip_type)
+{
+ return altcp_tls_new((struct altcp_tls_config *)arg, ip_type);
+}
+
+#endif /* TRANSPORT_ALTCP_TLS */
+
+#endif /* TRANSPORT_ALTCP */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_tcp.c b/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_tcp.c
new file mode 100644
index 00000000000000..c0119bd015e3b3
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_tcp.c
@@ -0,0 +1,563 @@
+/**
+ * @file
+ * Application layered TCP connection API (to be used from TCPIP thread)\n
+ * This interface mimics the tcp callback API to the application while preventing
+ * direct linking (much like virtual functions).
+ * This way, an application can make use of other application layer protocols
+ * on top of TCP without knowing the details (e.g. TLS, proxy connection).
+ *
+ * This file contains the base implementation calling into tcp.
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ */
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#include "altcp.h"
+#include "altcp_tcp.h"
+#include "altcp_priv.h"
+#include "lwip/tcp.h"
+
+#include
+
+#define ALTCP_TCP_ASSERT_CONN(conn) do { \
+ TRANSPORT_ASSERT("conn->inner_conn == NULL", (conn)->inner_conn == NULL); \
+ TRANSPORT_UNUSED_ARG(conn); /* for LWIP_NOASSERT */ } while(0)
+#define ALTCP_TCP_ASSERT_CONN_PCB(conn, tpcb) do { \
+ TRANSPORT_ASSERT("pcb mismatch", (conn)->state == tpcb); \
+ TRANSPORT_UNUSED_ARG(tpcb); /* for LWIP_NOASSERT */ \
+ ALTCP_TCP_ASSERT_CONN(conn); } while(0)
+
+
+/* Variable prototype, the actual declaration is at the end of this file
+ since it contains pointers to static functions declared here */
+extern const struct altcp_functions altcp_tcp_functions;
+
+static void altcp_tcp_setup(struct altcp_pcb *conn, struct tcp_pcb *tpcb);
+
+/* callback functions for TCP */
+static err_t
+altcp_tcp_accept(void *arg, struct tcp_pcb *new_tpcb, err_t err)
+{
+ struct altcp_pcb *listen_conn = (struct altcp_pcb *)arg;
+ if (listen_conn && listen_conn->accept) {
+ /* create a new altcp_conn to pass to the next 'accept' callback */
+ struct altcp_pcb *new_conn = altcp_alloc();
+ if (new_conn == NULL) {
+ return ERR_MEM;
+ }
+ altcp_tcp_setup(new_conn, new_tpcb);
+ return listen_conn->accept(listen_conn->arg, new_conn, err);
+ }
+ return ERR_ARG;
+}
+
+static err_t
+altcp_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
+{
+ struct altcp_pcb *conn = (struct altcp_pcb *)arg;
+ if (conn) {
+ ALTCP_TCP_ASSERT_CONN_PCB(conn, tpcb);
+ if (conn->connected) {
+ return conn->connected(conn->arg, conn, err);
+ }
+ }
+ return ERR_OK;
+}
+
+static err_t
+altcp_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
+{
+ struct altcp_pcb *conn = (struct altcp_pcb *)arg;
+ if (conn) {
+ ALTCP_TCP_ASSERT_CONN_PCB(conn, tpcb);
+ if (conn->recv) {
+ return conn->recv(conn->arg, conn, p, err);
+ }
+ }
+ if (p != NULL) {
+ /* prevent memory leaks */
+ pbuf_free(p);
+ }
+ return ERR_OK;
+}
+
+static err_t
+altcp_tcp_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
+{
+ struct altcp_pcb *conn = (struct altcp_pcb *)arg;
+ if (conn) {
+ ALTCP_TCP_ASSERT_CONN_PCB(conn, tpcb);
+ if (conn->sent) {
+ return conn->sent(conn->arg, conn, len);
+ }
+ }
+ return ERR_OK;
+}
+
+static err_t
+altcp_tcp_poll(void *arg, struct tcp_pcb *tpcb)
+{
+ struct altcp_pcb *conn = (struct altcp_pcb *)arg;
+ if (conn) {
+ ALTCP_TCP_ASSERT_CONN_PCB(conn, tpcb);
+ if (conn->poll) {
+ return conn->poll(conn->arg, conn);
+ }
+ }
+ return ERR_OK;
+}
+
+static void
+altcp_tcp_err(void *arg, err_t err)
+{
+ struct altcp_pcb *conn = (struct altcp_pcb *)arg;
+ if (conn) {
+ conn->state = NULL; /* already freed */
+ if (conn->err) {
+ conn->err(conn->arg, err);
+ }
+ altcp_free(conn);
+ }
+}
+
+/* setup functions */
+
+static void
+altcp_tcp_remove_callbacks(struct tcp_pcb *tpcb)
+{
+ tcp_arg(tpcb, NULL);
+ tcp_recv(tpcb, NULL);
+ tcp_sent(tpcb, NULL);
+ tcp_err(tpcb, NULL);
+ tcp_poll(tpcb, NULL, tpcb->pollinterval);
+}
+
+static void
+altcp_tcp_setup_callbacks(struct altcp_pcb *conn, struct tcp_pcb *tpcb)
+{
+ tcp_arg(tpcb, conn);
+ tcp_recv(tpcb, altcp_tcp_recv);
+ tcp_sent(tpcb, altcp_tcp_sent);
+ tcp_err(tpcb, altcp_tcp_err);
+ /* tcp_poll is set when interval is set by application */
+ /* listen is set totally different :-) */
+}
+
+static void
+altcp_tcp_setup(struct altcp_pcb *conn, struct tcp_pcb *tpcb)
+{
+ altcp_tcp_setup_callbacks(conn, tpcb);
+ conn->state = tpcb;
+ conn->fns = &altcp_tcp_functions;
+}
+
+struct altcp_pcb *
+altcp_tcp_new_ip_type(u8_t ip_type)
+{
+ /* Allocate the tcp pcb first to invoke the priority handling code
+ if we're out of pcbs */
+ struct tcp_pcb *tpcb = tcp_new_ip_type(ip_type);
+ if (tpcb != NULL) {
+ struct altcp_pcb *ret = altcp_alloc();
+ if (ret != NULL) {
+ altcp_tcp_setup(ret, tpcb);
+ return ret;
+ } else {
+ /* altcp_pcb allocation failed -> free the tcp_pcb too */
+ tcp_close(tpcb);
+ }
+ }
+ return NULL;
+}
+
+/** altcp_tcp allocator function fitting to @ref altcp_allocator_t / @ref altcp_new.
+*
+* arg pointer is not used for TCP.
+*/
+struct altcp_pcb *
+altcp_tcp_alloc(void *arg, u8_t ip_type)
+{
+ TRANSPORT_UNUSED_ARG(arg);
+ return altcp_tcp_new_ip_type(ip_type);
+}
+
+struct altcp_pcb *
+altcp_tcp_wrap(struct tcp_pcb *tpcb)
+{
+ if (tpcb != NULL) {
+ struct altcp_pcb *ret = altcp_alloc();
+ if (ret != NULL) {
+ altcp_tcp_setup(ret, tpcb);
+ return ret;
+ }
+ }
+ return NULL;
+}
+
+
+/* "virtual" functions calling into tcp */
+static void
+altcp_tcp_set_poll(struct altcp_pcb *conn, u8_t interval)
+{
+ if (conn != NULL) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+ tcp_poll(pcb, altcp_tcp_poll, interval);
+ }
+}
+
+static void
+altcp_tcp_recved(struct altcp_pcb *conn, u16_t len)
+{
+ if (conn != NULL) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+ tcp_recved(pcb, len);
+ }
+}
+
+static err_t
+altcp_tcp_bind(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port)
+{
+ struct tcp_pcb *pcb;
+ if (conn == NULL) {
+ return ERR_VAL;
+ }
+ ALTCP_TCP_ASSERT_CONN(conn);
+ pcb = (struct tcp_pcb *)conn->state;
+ return tcp_bind(pcb, ipaddr, port);
+}
+
+static err_t
+altcp_tcp_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected)
+{
+ struct tcp_pcb *pcb;
+ if (conn == NULL) {
+ return ERR_VAL;
+ }
+ ALTCP_TCP_ASSERT_CONN(conn);
+ conn->connected = connected;
+ pcb = (struct tcp_pcb *)conn->state;
+ return tcp_connect(pcb, ipaddr, port, altcp_tcp_connected);
+}
+
+static struct altcp_pcb *
+altcp_tcp_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err)
+{
+ struct tcp_pcb *pcb;
+ struct tcp_pcb *lpcb;
+ if (conn == NULL) {
+ return NULL;
+ }
+ ALTCP_TCP_ASSERT_CONN(conn);
+ pcb = (struct tcp_pcb *)conn->state;
+ lpcb = tcp_listen_with_backlog_and_err(pcb, backlog, err);
+ if (lpcb != NULL) {
+ conn->state = lpcb;
+ tcp_accept(lpcb, altcp_tcp_accept);
+ return conn;
+ }
+ return NULL;
+}
+
+static void
+altcp_tcp_abort(struct altcp_pcb *conn)
+{
+ if (conn != NULL) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+ if (pcb) {
+ tcp_abort(pcb);
+ }
+ }
+}
+
+static err_t
+altcp_tcp_close(struct altcp_pcb *conn)
+{
+ struct tcp_pcb *pcb;
+ if (conn == NULL) {
+ return ERR_VAL;
+ }
+ ALTCP_TCP_ASSERT_CONN(conn);
+ pcb = (struct tcp_pcb *)conn->state;
+ if (pcb) {
+ err_t err;
+ tcp_poll_fn oldpoll = pcb->poll;
+ altcp_tcp_remove_callbacks(pcb);
+ err = tcp_close(pcb);
+ if (err != ERR_OK) {
+ /* not closed, set up all callbacks again */
+ altcp_tcp_setup_callbacks(conn, pcb);
+ /* poll callback is not included in the above */
+ tcp_poll(pcb, oldpoll, pcb->pollinterval);
+ return err;
+ }
+ conn->state = NULL; /* unsafe to reference pcb after tcp_close(). */
+ }
+ altcp_free(conn);
+ return ERR_OK;
+}
+
+static err_t
+altcp_tcp_shutdown(struct altcp_pcb *conn, int shut_rx, int shut_tx)
+{
+ struct tcp_pcb *pcb;
+ if (conn == NULL) {
+ return ERR_VAL;
+ }
+ ALTCP_TCP_ASSERT_CONN(conn);
+ pcb = (struct tcp_pcb *)conn->state;
+ return tcp_shutdown(pcb, shut_rx, shut_tx);
+}
+
+static err_t
+altcp_tcp_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags)
+{
+ struct tcp_pcb *pcb;
+ if (conn == NULL) {
+ return ERR_VAL;
+ }
+ ALTCP_TCP_ASSERT_CONN(conn);
+ pcb = (struct tcp_pcb *)conn->state;
+ return tcp_write(pcb, dataptr, len, apiflags);
+}
+
+static err_t
+altcp_tcp_output(struct altcp_pcb *conn)
+{
+ struct tcp_pcb *pcb;
+ if (conn == NULL) {
+ return ERR_VAL;
+ }
+ ALTCP_TCP_ASSERT_CONN(conn);
+ pcb = (struct tcp_pcb *)conn->state;
+ return tcp_output(pcb);
+}
+
+static u16_t
+altcp_tcp_mss(struct altcp_pcb *conn)
+{
+ struct tcp_pcb *pcb;
+ if (conn == NULL) {
+ return 0;
+ }
+ ALTCP_TCP_ASSERT_CONN(conn);
+ pcb = (struct tcp_pcb *)conn->state;
+ return tcp_mss(pcb);
+}
+
+static u16_t
+altcp_tcp_sndbuf(struct altcp_pcb *conn)
+{
+ struct tcp_pcb *pcb;
+ if (conn == NULL) {
+ return 0;
+ }
+ ALTCP_TCP_ASSERT_CONN(conn);
+ pcb = (struct tcp_pcb *)conn->state;
+ return tcp_sndbuf(pcb);
+}
+
+static u16_t
+altcp_tcp_sndqueuelen(struct altcp_pcb *conn)
+{
+ struct tcp_pcb *pcb;
+ if (conn == NULL) {
+ return 0;
+ }
+ ALTCP_TCP_ASSERT_CONN(conn);
+ pcb = (struct tcp_pcb *)conn->state;
+ return tcp_sndqueuelen(pcb);
+}
+
+static void
+altcp_tcp_nagle_disable(struct altcp_pcb *conn)
+{
+ if (conn && conn->state) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+ tcp_nagle_disable(pcb);
+ }
+}
+
+static void
+altcp_tcp_nagle_enable(struct altcp_pcb *conn)
+{
+ if (conn && conn->state) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+ tcp_nagle_enable(pcb);
+ }
+}
+
+static int
+altcp_tcp_nagle_disabled(struct altcp_pcb *conn)
+{
+ if (conn && conn->state) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+ return tcp_nagle_disabled(pcb);
+ }
+ return 0;
+}
+
+static void
+altcp_tcp_setprio(struct altcp_pcb *conn, u8_t prio)
+{
+ if (conn != NULL) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+ tcp_setprio(pcb, prio);
+ }
+}
+
+static void
+altcp_tcp_dealloc(struct altcp_pcb *conn)
+{
+ TRANSPORT_UNUSED_ARG(conn);
+ ALTCP_TCP_ASSERT_CONN(conn);
+ /* no private state to clean up */
+}
+
+static err_t
+altcp_tcp_get_tcp_addrinfo(struct altcp_pcb *conn, int local, ip_addr_t *addr, u16_t *port)
+{
+ if (conn) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+#if 0
+ if (pcb) {
+ if (local) {
+ if (addr) {
+ *addr = pcb->local_ip;
+ }
+ if (port) {
+ *port = pcb->local_port;
+ }
+ } else {
+ if (addr) {
+ *addr = pcb->remote_ip;
+ }
+ if (port) {
+ *port = pcb->remote_port;
+ }
+ }
+ return ERR_OK;
+ }
+ return ERR_VAL;
+#endif
+ return tcp_tcp_get_tcp_addrinfo(pcb, local, addr, port);
+ }
+ return ERR_VAL;
+}
+
+static ip_addr_t *
+altcp_tcp_get_ip(struct altcp_pcb *conn, int local)
+{
+ if (conn) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+ if (pcb) {
+ if (local) {
+ return &pcb->local_ip;
+ } else {
+ return &pcb->remote_ip;
+ }
+ }
+ }
+ return NULL;
+}
+
+static u16_t
+altcp_tcp_get_port(struct altcp_pcb *conn, int local)
+{
+ if (conn) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+ if (pcb) {
+ if (local) {
+ return pcb->local_port;
+ } else {
+ return pcb->remote_port;
+ }
+ }
+ }
+ return 0;
+}
+
+#ifdef ALTCP_DEBUG
+static enum tcp_state
+altcp_tcp_dbg_get_tcp_state(struct altcp_pcb *conn)
+{
+ if (conn) {
+ struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state;
+ ALTCP_TCP_ASSERT_CONN(conn);
+ if (pcb) {
+ return pcb->state;
+ }
+ }
+ return CLOSED;
+}
+#endif
+const struct altcp_functions altcp_tcp_functions = {
+ altcp_tcp_set_poll,
+ altcp_tcp_recved,
+ altcp_tcp_bind,
+ altcp_tcp_connect,
+ altcp_tcp_listen,
+ altcp_tcp_abort,
+ altcp_tcp_close,
+ altcp_tcp_shutdown,
+ altcp_tcp_write,
+ altcp_tcp_output,
+ altcp_tcp_mss,
+ altcp_tcp_sndbuf,
+ altcp_tcp_sndqueuelen,
+ altcp_tcp_nagle_disable,
+ altcp_tcp_nagle_enable,
+ altcp_tcp_nagle_disabled,
+ altcp_tcp_setprio,
+ altcp_tcp_dealloc,
+ altcp_tcp_get_tcp_addrinfo,
+ altcp_tcp_get_ip,
+ altcp_tcp_get_port
+#ifdef ALTCP_DEBUG
+ , altcp_tcp_dbg_get_tcp_state
+#endif
+};
+
+#endif /* TRANSPORT_ALTCP */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_tls_mbedtls.c b/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_tls_mbedtls.c
new file mode 100644
index 00000000000000..388013a57ae091
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_tls_mbedtls.c
@@ -0,0 +1,1247 @@
+/**
+ * @file
+ * Application layered TCP/TLS connection API (to be used from TCPIP thread)
+ *
+ * This file provides a TLS layer using mbedTLS
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ * Watch out:
+ * - 'sent' is always called with len==0 to the upper layer. This is because keeping
+ * track of the ratio of application data and TLS overhead would be too much.
+ *
+ * Mandatory security-related configuration:
+ * - define ALTCP_MBEDTLS_RNG_FN to mbedtls_entropy_func to use the standard mbedTLS
+ * entropy and ensure to add at least one strong entropy source to your mbedtls port
+ * (implement mbedtls_platform_entropy_poll or mbedtls_hardware_poll providing strong
+ * entropy)
+ * - define ALTCP_MBEDTLS_ENTROPY_PTR and ALTCP_MBEDTLS_ENTROPY_LEN to something providing
+ * GOOD custom entropy
+ *
+ * Missing things / @todo:
+ * - some unhandled/untested things migh be caught by TRANSPORT_ASSERTs...
+ */
+
+#include "altcp_opt.h"
+#include "AppConfig.h"
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#include "altcp_tls_mbedtls_opts.h"
+
+#if TRANSPORT_ALTCP_TLS && TRANSPORT_ALTCP_TLS_MBEDTLS
+#define MBEDTLS_ALLOW_PRIVATE_ACCESS
+#ifndef SIWX_917
+#include "mbedtls/private_access.h"
+#include "ssl_misc.h"
+#endif
+
+#include "mbedtls/ssl.h"
+
+#include "altcp.h"
+#include "altcp_tls.h"
+#include "altcp_priv.h"
+
+#include "altcp_tls_mbedtls_structs.h"
+#include "altcp_tls_mbedtls_mem.h"
+
+/* @todo: which includes are really needed? */
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+// #include "mbedtls/certs.h"
+#include "mbedtls/x509.h"
+//#include "mbedtls/net.h"
+#include "mbedtls/net_sockets.h"
+#include "mbedtls/error.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/platform.h"
+#include "mbedtls/memory_buffer_alloc.h"
+#include "mbedtls/ssl_cache.h"
+
+
+
+// #include "mbedtls/ssl_internal.h" /* to call mbedtls_flush_output after ERR_MEM */
+
+#include
+
+#ifndef ALTCP_MBEDTLS_ENTROPY_PTR
+#define ALTCP_MBEDTLS_ENTROPY_PTR NULL
+#endif
+#ifndef ALTCP_MBEDTLS_ENTROPY_LEN
+#define ALTCP_MBEDTLS_ENTROPY_LEN 0
+#endif
+
+/* Variable prototype, the actual declaration is at the end of this file
+ since it contains pointers to static functions declared here */
+extern const struct altcp_functions altcp_mbedtls_functions;
+
+/** Our global mbedTLS configuration (server-specific, not connection-specific) */
+struct altcp_tls_config {
+ mbedtls_ssl_config conf;
+ mbedtls_entropy_context entropy;
+ mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_x509_crt *cert;
+ mbedtls_pk_context *pkey;
+ mbedtls_x509_crt *ca;
+#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS
+ /** Inter-connection cache for fast connection startup */
+ struct mbedtls_ssl_cache_context cache;
+#endif
+};
+
+static err_t altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err);
+static err_t altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn);
+//static err_t altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t *state);
+static err_t altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state);
+static int altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size);
+static void altcp_mbedtls_lower_recv_signal(struct altcp_pcb *conn);
+
+/* callback functions from inner/lower connection: */
+
+/** Accept callback from lower connection (i.e. TCP)
+ * Allocate one of our structures, assign it to the new connection's 'state' and
+ * call the new connection's 'accepted' callback. If that succeeds, we wait
+ * to receive connection setup handshake bytes from the client.
+ */
+static err_t
+altcp_mbedtls_lower_accept(void *arg, struct altcp_pcb *accepted_conn, err_t err)
+{
+ struct altcp_pcb *listen_conn = (struct altcp_pcb *)arg;
+ if (listen_conn && listen_conn->state && listen_conn->accept) {
+ err_t setup_err;
+ altcp_mbedtls_state_t *listen_state = (altcp_mbedtls_state_t *)listen_conn->state;
+ /* create a new altcp_conn to pass to the next 'accept' callback */
+ struct altcp_pcb *new_conn = altcp_alloc();
+ if (new_conn == NULL) {
+ return ERR_MEM;
+ }
+ setup_err = altcp_mbedtls_setup(listen_state->conf, new_conn, accepted_conn);
+ if (setup_err != ERR_OK) {
+ altcp_free(new_conn);
+ return setup_err;
+ }
+ return listen_conn->accept(listen_conn->arg, new_conn, err);
+ }
+ return ERR_ARG;
+}
+
+/** Connected callback from lower connection (i.e. TCP).
+ * Not really implemented/tested yet...
+ */
+static err_t
+altcp_mbedtls_lower_connected(void *arg, struct altcp_pcb *inner_conn, err_t err)
+{
+ struct altcp_pcb *conn = (struct altcp_pcb *)arg;
+ TRANSPORT_UNUSED_ARG(inner_conn); /* for TRANSPORT_NOASSERT */
+ SILABS_LOG("tcp conn status %d", err);
+ if (conn && conn->state) {
+ SILABS_LOG("tcp conn status %d", err);
+ TRANSPORT_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
+ /* upper connected is called when handshake is done */
+ if (err != ERR_OK) {
+ if (conn->connected) {
+ SILABS_LOG("tcp conn status %d", err);
+ return conn->connected(conn->arg, conn, err);
+ }
+ }
+ //return altcp_mbedtls_lower_recv_process(conn, (altcp_mbedtls_state_t *)conn->state);
+ altcp_mbedtls_lower_recv_signal(conn);
+ return ERR_OK;
+ }
+ return ERR_VAL;
+}
+
+/* Call recved for possibly more than an u16_t */
+static void
+altcp_mbedtls_lower_recved(struct altcp_pcb *inner_conn, int recvd_cnt)
+{
+ while (recvd_cnt > 0) {
+ u16_t recvd_part = (u16_t)TRANSPORT_MIN(recvd_cnt, 0xFFFF);
+ altcp_recved(inner_conn, recvd_part);
+ recvd_cnt -= recvd_part;
+ }
+}
+
+/** Recv callback from lower connection (i.e. TCP)
+ * This one mainly differs between connection setup/handshake (data is fed into mbedTLS only)
+ * and application phase (data is decoded by mbedTLS and passed on to the application).
+ */
+static err_t
+altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err)
+{
+ altcp_mbedtls_state_t *state;
+ struct altcp_pcb *conn = (struct altcp_pcb *)arg;
+
+ TRANSPORT_ASSERT("no err expected", err == ERR_OK);
+ TRANSPORT_UNUSED_ARG(err);
+
+ if (!conn) {
+ /* no connection given as arg? should not happen, but prevent pbuf/conn leaks */
+ if (p != NULL) {
+ pbuf_free(p);
+ }
+ altcp_close(inner_conn);
+ return ERR_CLSD;
+ }
+ state = (altcp_mbedtls_state_t *)conn->state;
+ TRANSPORT_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
+ if (!state) {
+ /* already closed */
+ if (p != NULL) {
+ pbuf_free(p);
+ }
+ altcp_close(inner_conn);
+ return ERR_CLSD;
+ }
+
+ /* handle NULL pbuf (inner connection closed) */
+ if (p == NULL) {
+ /* remote host sent FIN, remember this (SSL state is destroyed
+ when both sides are closed only!) */
+ if ((state->flags & (ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE | ALTCP_MBEDTLS_FLAGS_UPPER_CALLED)) ==
+ (ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE | ALTCP_MBEDTLS_FLAGS_UPPER_CALLED)) {
+ /* need to notify upper layer (e.g. 'accept' called or 'connect' succeeded) */
+ if ((state->rx != NULL) || (state->rx_app != NULL)) {
+ state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED;
+ /* this is a normal close (FIN) but we have unprocessed data, so delay the FIN */
+ altcp_mbedtls_handle_rx_appldata(conn, state);
+ return ERR_OK;
+ }
+ state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED;
+ if (conn->recv) {
+ return conn->recv(conn->arg, conn, NULL, ERR_OK);
+ }
+ } else {
+ /* before connection setup is done: call 'err' */
+ if (conn->err) {
+ conn->err(conn->arg, ERR_CLSD);
+ }
+ altcp_close(conn);
+ }
+ return ERR_OK;
+ }
+
+ /* If we come here, the connection is in good state (handshake phase or application data phase).
+ Queue up the pbuf for processing as handshake data or application data. */
+ if (state->rx == NULL) {
+ state->rx = p;
+ } else {
+ TRANSPORT_ASSERT("rx pbuf overflow", (int)p->tot_len + (int)p->len <= 0xFFFF);
+ pbuf_cat(state->rx, p);
+ }
+ //return altcp_mbedtls_lower_recv_process(conn, state);
+ /* signal application to process rx packet and return success*/
+ altcp_mbedtls_lower_recv_signal(conn);
+ return ERR_OK;
+}
+
+static void altcp_mbedtls_lower_recv_signal(struct altcp_pcb *conn)
+{
+ extern void mbedtls_signal_app(void *arg);
+ mbedtls_signal_app(conn->arg);
+}
+
+err_t
+altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn)
+ {
+ altcp_mbedtls_state_t *state;
+ if (conn == NULL || conn->state == NULL) return ERR_ARG;
+ state = (altcp_mbedtls_state_t *)conn->state;
+
+ if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
+ /* handle connection setup (handshake not done) */
+ int ret = mbedtls_ssl_handshake(&state->ssl_context);
+ /* try to send data... */
+ altcp_output(conn->inner_conn);
+ if (state->bio_bytes_read) {
+ /* acknowledge all bytes read */
+ altcp_mbedtls_lower_recved(conn->inner_conn, state->bio_bytes_read);
+ state->bio_bytes_read = 0;
+ }
+
+ if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
+ /* handshake not done, wait for more recv calls */
+ return ERR_OK;
+ }
+ if (ret != 0) {
+ SILABS_LOG("mbedtls_ssl_handshake failed: %d\n", ret);
+ /* handshake failed, connection has to be closed */
+ if (conn->err) {
+ conn->err(conn->arg, ERR_CLSD);
+ }
+
+ if (altcp_close(conn) != ERR_OK) {
+ altcp_abort(conn);
+ }
+ return ERR_OK;
+ }
+ /* If we come here, handshake succeeded. */
+ TRANSPORT_ASSERT("state", state->bio_bytes_read == 0);
+ TRANSPORT_ASSERT("state", state->bio_bytes_appl == 0);
+ state->flags |= ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE;
+ /* issue "connect" callback" to upper connection (this can only happen for active open) */
+ if (conn->connected) {
+ err_t err;
+ err = conn->connected(conn->arg, conn, ERR_OK);
+ if (err != ERR_OK) {
+ return err;
+ }
+ }
+ if (state->rx == NULL) {
+ return ERR_OK;
+ }
+ }
+ /* handle application data */
+ return altcp_mbedtls_handle_rx_appldata(conn, state);
+}
+
+/* Pass queued decoded rx data to application */
+static err_t
+altcp_mbedtls_pass_rx_data(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
+{
+ err_t err;
+ struct pbuf *buf;
+ TRANSPORT_ASSERT("conn != NULL", conn != NULL);
+ TRANSPORT_ASSERT("state != NULL", state != NULL);
+ buf = state->rx_app;
+ if (buf) {
+ state->rx_app = NULL;
+ if (conn->recv) {
+ u16_t tot_len = buf->tot_len;
+ /* this needs to be increased first because the 'recved' call may come nested */
+ state->rx_passed_unrecved += tot_len;
+ state->flags |= ALTCP_MBEDTLS_FLAGS_UPPER_CALLED;
+ err = conn->recv(conn->arg, conn, buf, ERR_OK);
+ if (err != ERR_OK) {
+ if (err == ERR_ABRT) {
+ return ERR_ABRT;
+ }
+ /* not received, leave the pbuf(s) queued (and decrease 'unrecved' again) */
+ TRANSPORT_ASSERT("state == conn->state", state == conn->state);
+ state->rx_app = buf;
+ state->rx_passed_unrecved -= tot_len;
+ TRANSPORT_ASSERT("state->rx_passed_unrecved >= 0", state->rx_passed_unrecved >= 0);
+ if (state->rx_passed_unrecved < 0) {
+ state->rx_passed_unrecved = 0;
+ }
+ return err;
+ }
+ } else {
+ pbuf_free(buf);
+ }
+ } else if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) ==
+ ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) {
+ state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED;
+ if (conn->recv) {
+ return conn->recv(conn->arg, conn, NULL, ERR_OK);
+ }
+ }
+
+ /* application may have close the connection */
+ if (conn->state != state) {
+ /* return error code to ensure altcp_mbedtls_handle_rx_appldata() exits the loop */
+ return ERR_CLSD;
+ }
+ return ERR_OK;
+}
+
+/* Helper function that processes rx application data stored in rx pbuf chain */
+static err_t
+altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state)
+{
+ int ret;
+ TRANSPORT_ASSERT("state != NULL", state != NULL);
+ if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
+ /* handshake not done yet */
+ return ERR_VAL;
+ }
+ do {
+ /* allocate a full-sized unchained PBUF_POOL: this is for RX! */
+ struct pbuf *buf = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL);
+ if (buf == NULL) {
+ /* We're short on pbufs, try again later from 'poll' or 'recv' callbacks.
+ @todo: close on excessive allocation failures or leave this up to upper conn? */
+ return ERR_OK;
+ }
+
+ /* decrypt application data, this pulls encrypted RX data off state->rx pbuf chain */
+ ret = mbedtls_ssl_read(&state->ssl_context, (unsigned char *)buf->payload, PBUF_POOL_BUFSIZE);
+ if (ret < 0) {
+ if (ret == MBEDTLS_ERR_SSL_CLIENT_RECONNECT) {
+ /* client is initiating a new connection using the same source port -> close connection or make handshake */
+ TRANSPORT_DEBUGF( ("new connection on same source port\n"));
+ TRANSPORT_ASSERT("TODO: new connection on same source port, close this connection", 0);
+ } else if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) {
+ if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
+ TRANSPORT_DEBUGF( ("connection was closed gracefully\n"));
+ } else if (ret == MBEDTLS_ERR_NET_CONN_RESET) {
+ TRANSPORT_DEBUGF( ("connection was reset by peer\n"));
+ }
+ pbuf_free(buf);
+ return ERR_OK;
+ } else {
+ pbuf_free(buf);
+ return ERR_OK;
+ }
+ pbuf_free(buf);
+ altcp_abort(conn);
+ return ERR_ABRT;
+ } else {
+ err_t err;
+ if (ret) {
+ TRANSPORT_ASSERT("bogus receive length", ret <= PBUF_POOL_BUFSIZE);
+ /* trim pool pbuf to actually decoded length */
+ pbuf_realloc(buf, (u16_t)ret);
+
+ state->bio_bytes_appl += ret;
+ if (mbedtls_ssl_get_bytes_avail(&state->ssl_context) == 0) {
+ /* Record is done, now we know the share between application and protocol bytes
+ and can adjust the RX window by the protocol bytes.
+ The rest is 'recved' by the application calling our 'recved' fn. */
+ int overhead_bytes;
+ TRANSPORT_ASSERT("bogus byte counts", state->bio_bytes_read > state->bio_bytes_appl);
+ overhead_bytes = state->bio_bytes_read - state->bio_bytes_appl;
+ altcp_mbedtls_lower_recved(conn->inner_conn, overhead_bytes);
+ state->bio_bytes_read = 0;
+ state->bio_bytes_appl = 0;
+ }
+
+ if (state->rx_app == NULL) {
+ state->rx_app = buf;
+ } else {
+ pbuf_cat(state->rx_app, buf);
+ }
+ } else {
+ pbuf_free(buf);
+ buf = NULL;
+ }
+ err = altcp_mbedtls_pass_rx_data(conn, state);
+ if (err != ERR_OK) {
+ if (err == ERR_ABRT) {
+ /* recv callback needs to return this as the pcb is deallocated */
+ return ERR_ABRT;
+ }
+ /* we hide all other errors as we retry feeding the pbuf to the app later */
+ return ERR_OK;
+ }
+ }
+ } while (ret > 0);
+ return ERR_OK;
+}
+
+/** Receive callback function called from mbedtls (set via mbedtls_ssl_set_bio)
+ * This function mainly copies data from pbufs and frees the pbufs after copying.
+ */
+static int
+altcp_mbedtls_bio_recv(void *ctx, unsigned char *buf, size_t len)
+{
+ struct altcp_pcb *conn = (struct altcp_pcb *)ctx;
+ altcp_mbedtls_state_t *state;
+ struct pbuf *p;
+ u16_t ret;
+ u16_t copy_len;
+ err_t err;
+
+ TRANSPORT_UNUSED_ARG(err); /* for TRANSPORT_NOASSERT */
+ if ((conn == NULL) || (conn->state == NULL)) {
+ return MBEDTLS_ERR_NET_INVALID_CONTEXT;
+ }
+ state = (altcp_mbedtls_state_t *)conn->state;
+ p = state->rx;
+
+ /* @todo: return MBEDTLS_ERR_NET_CONN_RESET/MBEDTLS_ERR_NET_RECV_FAILED? */
+
+ if ((p == NULL) || ((p->len == 0) && (p->next == NULL))) {
+ if (p) {
+ pbuf_free(p);
+ }
+ state->rx = NULL;
+ if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) ==
+ ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) {
+ /* close queued but not passed up yet */
+ return 0;
+ }
+ return MBEDTLS_ERR_SSL_WANT_READ;
+ }
+ /* limit number of bytes again to copy from first pbuf in a chain only */
+ copy_len = (u16_t)TRANSPORT_MIN(len, p->len);
+ /* copy the data */
+ ret = pbuf_copy_partial(p, buf, copy_len, 0);
+ TRANSPORT_ASSERT("ret == copy_len", ret == copy_len);
+ /* hide the copied bytes from the pbuf */
+ err = pbuf_remove_header(p, ret);
+ TRANSPORT_ASSERT("error", err == ERR_OK);
+ if (p->len == 0) {
+ /* the first pbuf has been fully read, free it */
+ state->rx = p->next;
+ p->next = NULL;
+ pbuf_free(p);
+ }
+
+ state->bio_bytes_read += (int)ret;
+ return ret;
+}
+
+/** Sent callback from lower connection (i.e. TCP)
+ * This only informs the upper layer to try to send more, not about
+ * the number of ACKed bytes.
+ */
+static err_t
+altcp_mbedtls_lower_sent(void *arg, struct altcp_pcb *inner_conn, u16_t len)
+{
+ int ret;
+ struct altcp_pcb *conn = (struct altcp_pcb *)arg;
+ TRANSPORT_UNUSED_ARG(inner_conn); /* for TRANSPORT_NOASSERT */
+ TRANSPORT_UNUSED_ARG(len);
+ if (conn) {
+ altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
+ TRANSPORT_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
+ if (!state || !(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
+ /* @todo: do something here? */
+ return ERR_OK;
+ }
+ /* try to send more if we failed before */
+ ret = mbedtls_ssl_flush_output(&state->ssl_context);
+ if(ret != 0){
+ TRANSPORT_DEBUGF(("mbedtls_ssl_flash_output failed\n"));
+ return ret;
+ }
+ /* call upper sent with len==0 if the application already sent data */
+ if ((state->flags & ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT) && conn->sent) {
+ return conn->sent(conn->arg, conn, 0);
+ }
+ }
+ return ERR_OK;
+}
+
+/** Poll callback from lower connection (i.e. TCP)
+ * Just pass this on to the application.
+ * @todo: retry sending?
+ */
+static err_t
+altcp_mbedtls_lower_poll(void *arg, struct altcp_pcb *inner_conn)
+{
+ int ret;
+ struct altcp_pcb *conn = (struct altcp_pcb *)arg;
+ TRANSPORT_UNUSED_ARG(inner_conn); /* for TRANSPORT_NOASSERT */
+ if (conn) {
+ TRANSPORT_ASSERT("pcb mismatch", conn->inner_conn == inner_conn);
+ /* check if there's unreceived rx data */
+ if (conn->state) {
+ altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
+ /* try to send more if we failed before */
+ ret = mbedtls_ssl_flush_output(&state->ssl_context);
+ if(ret != 0){
+ TRANSPORT_DEBUGF(("mbedtls_ssl_flash_output failed\n"));
+ return ret;
+ }
+ if (altcp_mbedtls_handle_rx_appldata(conn, state) == ERR_ABRT) {
+ return ERR_ABRT;
+ }
+ }
+ if (conn->poll) {
+ return conn->poll(conn->arg, conn);
+ }
+ }
+ return ERR_OK;
+}
+
+static void
+altcp_mbedtls_lower_err(void *arg, err_t err)
+{
+ struct altcp_pcb *conn = (struct altcp_pcb *)arg;
+ if (conn) {
+ conn->inner_conn = NULL; /* already freed */
+ if (conn->err) {
+ conn->err(conn->arg, err);
+ }
+ altcp_free(conn);
+ }
+}
+
+/* setup functions */
+
+static void
+altcp_mbedtls_remove_callbacks(struct altcp_pcb *inner_conn)
+{
+ altcp_arg(inner_conn, NULL);
+ altcp_recv(inner_conn, NULL);
+ altcp_sent(inner_conn, NULL);
+ altcp_err(inner_conn, NULL);
+ altcp_poll(inner_conn, NULL, inner_conn->pollinterval);
+}
+
+static void
+altcp_mbedtls_setup_callbacks(struct altcp_pcb *conn, struct altcp_pcb *inner_conn)
+{
+ altcp_arg(inner_conn, conn);
+ altcp_recv(inner_conn, altcp_mbedtls_lower_recv);
+ altcp_sent(inner_conn, altcp_mbedtls_lower_sent);
+ altcp_err(inner_conn, altcp_mbedtls_lower_err);
+ /* tcp_poll is set when interval is set by application */
+ /* listen is set totally different :-) */
+}
+
+static err_t
+altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn)
+{
+ int ret;
+ struct altcp_tls_config *config = (struct altcp_tls_config *)conf;
+ altcp_mbedtls_state_t *state;
+ if (!conf) {
+ return ERR_ARG;
+ }
+ TRANSPORT_ASSERT("invalid inner_conn", conn != inner_conn);
+
+ /* allocate mbedtls context */
+ state = altcp_mbedtls_alloc(conf);
+ if (state == NULL) {
+ return ERR_MEM;
+ }
+ /* initialize mbedtls context: */
+ mbedtls_ssl_init(&state->ssl_context);
+ ret = mbedtls_ssl_setup(&state->ssl_context, &config->conf);
+ if (ret != 0) {
+ TRANSPORT_DEBUGF(("mbedtls_ssl_setup failed\n"));
+ /* @todo: convert 'ret' to err_t */
+ altcp_mbedtls_free(conf, state);
+ return ERR_MEM;
+ }
+ /* tell mbedtls about our I/O functions */
+ mbedtls_ssl_set_bio(&state->ssl_context, conn, altcp_mbedtls_bio_send, altcp_mbedtls_bio_recv, NULL);
+
+ altcp_mbedtls_setup_callbacks(conn, inner_conn);
+ conn->inner_conn = inner_conn;
+ conn->fns = &altcp_mbedtls_functions;
+ conn->state = state;
+ return ERR_OK;
+}
+
+struct altcp_pcb *
+altcp_tls_wrap(struct altcp_tls_config *config, struct altcp_pcb *inner_pcb)
+{
+ struct altcp_pcb *ret;
+ if (inner_pcb == NULL) {
+ return NULL;
+ }
+ ret = altcp_alloc();
+ if (ret != NULL) {
+ if (altcp_mbedtls_setup(config, ret, inner_pcb) != ERR_OK) {
+ altcp_free(ret);
+ return NULL;
+ }
+ }
+ return ret;
+}
+
+void *
+altcp_tls_context(struct altcp_pcb *conn)
+{
+ if (conn && conn->state) {
+ altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
+ return &state->ssl_context;
+ }
+ return NULL;
+}
+
+#if ALTCP_MBEDTLS_DEBUG
+static void
+altcp_mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str)
+{
+ TRANSPORT_UNUSED_ARG(ctx);
+ TRANSPORT_UNUSED_ARG(level);
+ TRANSPORT_UNUSED_ARG(file);
+ TRANSPORT_UNUSED_ARG(line);
+ TRANSPORT_UNUSED_ARG(str);
+
+ TRANSPORT_DEBUGF(("%s:%04d: %s", file, line, str));
+}
+#endif
+
+#ifndef ALTCP_MBEDTLS_RNG_FN
+/** ATTENTION: It is *really* important to *NOT* use this dummy RNG in production code!!!! */
+static int
+dummy_rng(void *ctx, unsigned char *buffer, size_t len)
+{
+ static size_t ctr;
+ size_t i;
+ TRANSPORT_UNUSED_ARG(ctx);
+ for (i = 0; i < len; i++) {
+ buffer[i] = (unsigned char)++ctr;
+ }
+ return 0;
+}
+#define ALTCP_MBEDTLS_RNG_FN dummy_rng
+#endif /* ALTCP_MBEDTLS_RNG_FN */
+
+static int ciphers[] = {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ 0 };
+
+/** Create new TLS configuration
+ * ATTENTION: Server certificate and private key have to be added outside this function!
+ */
+static struct altcp_tls_config *
+altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca)
+{
+ size_t sz;
+ int ret;
+ struct altcp_tls_config *conf;
+ mbedtls_x509_crt *mem;
+
+ if (TCP_WND < MBEDTLS_SSL_MAX_CONTENT_LEN) {
+ TRANSPORT_DEBUGF(
+ ("altcp_tls: TCP_WND is smaller than the RX decryption buffer, connection RX might stall!\n"));
+ }
+
+ altcp_mbedtls_mem_init();
+
+ sz = sizeof(struct altcp_tls_config);
+ if (have_cert) {
+ sz += sizeof(mbedtls_x509_crt);
+ }
+ if (have_ca) {
+ sz += sizeof(mbedtls_x509_crt);
+ }
+ if (have_pkey) {
+ sz += sizeof(mbedtls_pk_context);
+ }
+
+ conf = (struct altcp_tls_config *)altcp_mbedtls_alloc_config(sz);
+ if (conf == NULL) {
+ return NULL;
+ }
+ mem = (mbedtls_x509_crt *)(conf + 1);
+ if (have_cert) {
+ conf->cert = mem;
+ mem++;
+ }
+ if (have_ca) {
+ conf->ca = mem;
+ mem++;
+ }
+ if (have_pkey) {
+ conf->pkey = (mbedtls_pk_context *)mem;
+ }
+
+ mbedtls_ssl_config_init(&conf->conf);
+ mbedtls_entropy_init(&conf->entropy);
+ mbedtls_ctr_drbg_init(&conf->ctr_drbg);
+
+ /* Seed the RNG */
+ ret = mbedtls_ctr_drbg_seed(&conf->ctr_drbg, ALTCP_MBEDTLS_RNG_FN, &conf->entropy, ALTCP_MBEDTLS_ENTROPY_PTR, ALTCP_MBEDTLS_ENTROPY_LEN);
+ if (ret != 0) {
+ TRANSPORT_DEBUGF( ("mbedtls_ctr_drbg_seed failed: %d\n", ret));
+ altcp_mbedtls_free_config(conf);
+ return NULL;
+ }
+
+ /* Setup ssl context (@todo: what's different for a client here? -> might better be done on listen/connect) */
+ ret = mbedtls_ssl_config_defaults(&conf->conf, is_server ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
+ MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
+
+ // const int ci[2] = {0x1302,0};
+
+ // mbedtls_ssl_conf_ciphersuites(&conf->conf, (const int *)ci);
+ if (ret != 0) {
+ TRANSPORT_DEBUGF( ("mbedtls_ssl_config_defaults failed: %d\n", ret));
+ altcp_mbedtls_free_config(conf);
+ return NULL;
+ }
+ mbedtls_ssl_conf_authmode(&conf->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+ mbedtls_ssl_conf_ciphersuites(&conf->conf, (const int *)&ciphers);
+ mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &conf->ctr_drbg);
+#if ALTCP_MBEDTLS_DEBUG
+ mbedtls_ssl_conf_dbg(&conf->conf, altcp_mbedtls_debug, stdout);
+ mbedtls_debug_set_threshold(1);
+#endif
+#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS
+ mbedtls_ssl_conf_session_cache(&conf->conf, &conf->cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set);
+ mbedtls_ssl_cache_set_timeout(&conf->cache, 30);
+ mbedtls_ssl_cache_set_max_entries(&conf->cache, 30);
+#endif
+
+ return conf;
+}
+
+/** Create new TLS configuration
+ * This is a suboptimal version that gets the encrypted private key and its password,
+ * as well as the server certificate.
+ */
+struct altcp_tls_config *
+altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len,
+ const u8_t *privkey_pass, size_t privkey_pass_len,
+ const u8_t *cert, size_t cert_len)
+{
+ int ret;
+ mbedtls_x509_crt *srvcert;
+ mbedtls_pk_context *pkey;
+ struct altcp_tls_config *conf = altcp_tls_create_config(1, 1, 1, 0);
+ if (conf == NULL) {
+ return NULL;
+ }
+
+ srvcert = conf->cert;
+ mbedtls_x509_crt_init(srvcert);
+
+ pkey = conf->pkey;
+ mbedtls_pk_init(pkey);
+
+ /* Load the certificates and private key */
+ ret = mbedtls_x509_crt_parse(srvcert, cert, cert_len);
+ if (ret != 0) {
+ TRANSPORT_DEBUGF( ("mbedtls_x509_crt_parse failed: %d\n", ret));
+ altcp_mbedtls_free_config(conf);
+ return NULL;
+ }
+
+#ifdef SIWX_917
+ ret = mbedtls_pk_parse_key(pkey, (const unsigned char *) privkey, privkey_len,
+ privkey_pass, privkey_pass_len);
+#else
+ ret = mbedtls_pk_parse_key(pkey, privkey, privkey_len, privkey_pass,
+ privkey_pass_len, ALTCP_MBEDTLS_RNG_FN, NULL);
+#endif
+
+ if (ret != 0) {
+ TRANSPORT_DEBUGF( ("mbedtls_pk_parse_public_key failed: %d\n", ret));
+ mbedtls_x509_crt_free(srvcert);
+ altcp_mbedtls_free_config(conf);
+ return NULL;
+ }
+
+ mbedtls_ssl_conf_ca_chain(&conf->conf, srvcert->next, NULL);
+ ret = mbedtls_ssl_conf_own_cert(&conf->conf, srvcert, pkey);
+ if (ret != 0) {
+ TRANSPORT_DEBUGF( ("mbedtls_ssl_conf_own_cert failed: %d\n", ret));
+ mbedtls_x509_crt_free(srvcert);
+ mbedtls_pk_free(pkey);
+ altcp_mbedtls_free_config(conf);
+ return NULL;
+ }
+ return conf;
+}
+
+static struct altcp_tls_config *
+altcp_tls_create_config_client_common(const u8_t *ca, size_t ca_len, int is_2wayauth)
+{
+ int ret;
+ struct altcp_tls_config *conf = altcp_tls_create_config(0, is_2wayauth, is_2wayauth, ca != NULL);
+ if (conf == NULL) {
+ return NULL;
+ }
+
+ /* Initialize the CA certificate if provided
+ * CA certificate is optional (to save memory) but recommended for production environment
+ * Without CA certificate, connection will be prone to man-in-the-middle attacks */
+ if (ca) {
+ mbedtls_x509_crt_init(conf->ca);
+ ret = mbedtls_x509_crt_parse(conf->ca, ca, ca_len);
+ if (ret != 0) {
+ TRANSPORT_DEBUGF(("mbedtls_x509_crt_parse ca failed: %d 0x%x", ret, -1*ret));
+ altcp_mbedtls_free_config(conf);
+ return NULL;
+ }
+
+ mbedtls_ssl_conf_ca_chain(&conf->conf, conf->ca, NULL);
+ }
+ return conf;
+}
+
+struct altcp_tls_config *
+altcp_tls_create_config_client(const u8_t *ca, size_t ca_len)
+{
+ return altcp_tls_create_config_client_common(ca, ca_len, 0);
+}
+
+struct altcp_tls_config *
+altcp_tls_create_config_client_2wayauth(const u8_t *ca, size_t ca_len, const u8_t *privkey, size_t privkey_len,
+ const u8_t *privkey_pass, size_t privkey_pass_len,
+ const u8_t *cert, size_t cert_len)
+{
+ int ret;
+ struct altcp_tls_config *conf;
+
+ if (!cert || !privkey) {
+ TRANSPORT_DEBUGF( ("altcp_tls_create_config_client_2wayauth: certificate and priv key required"));
+ return NULL;
+ }
+
+ conf = altcp_tls_create_config_client_common(ca, ca_len, 1);
+ if (conf == NULL) {
+ return NULL;
+ }
+
+ /* Initialize the client certificate and corresponding private key */
+ mbedtls_x509_crt_init(conf->cert);
+ ret = mbedtls_x509_crt_parse(conf->cert, cert, cert_len);
+ if (ret != 0) {
+ SILABS_LOG("mbedtls_x509_crt_parse cert failed: %d 0x%x", ret, -1*ret);
+ altcp_mbedtls_free_config(conf->cert);
+ return NULL;
+ }
+
+ mbedtls_pk_init(conf->pkey);
+#ifdef SIWX_917
+ ret = mbedtls_pk_parse_key(conf->pkey, (const unsigned char *) privkey, privkey_len,
+ privkey_pass, privkey_pass_len);
+#else
+ ret = mbedtls_pk_parse_key(conf->pkey, privkey, privkey_len, privkey_pass,
+ privkey_pass_len, ALTCP_MBEDTLS_RNG_FN, NULL);
+#endif
+ if (ret != 0) {
+ SILABS_LOG("mbedtls_pk_parse_key failed: %d 0x%x", ret, -1*ret);
+ altcp_mbedtls_free_config(conf);
+ return NULL;
+ }
+
+ ret = mbedtls_ssl_conf_own_cert(&conf->conf, conf->cert, conf->pkey);
+ if (ret != 0) {
+ SILABS_LOG("mbedtls_ssl_conf_own_cert failed: %d 0x%x", ret, -1*ret);
+ altcp_mbedtls_free_config(conf);
+ return NULL;
+ }
+
+ return conf;
+}
+
+void
+altcp_tls_free_config(struct altcp_tls_config *conf)
+{
+ if (conf->pkey) {
+ mbedtls_pk_free(conf->pkey);
+ }
+ if (conf->cert) {
+ mbedtls_x509_crt_free(conf->cert);
+ }
+ if (conf->ca) {
+ mbedtls_x509_crt_free(conf->ca);
+ }
+ altcp_mbedtls_free_config(conf);
+}
+
+/* "virtual" functions */
+static void
+altcp_mbedtls_set_poll(struct altcp_pcb *conn, u8_t interval)
+{
+ if (conn != NULL) {
+ altcp_poll(conn->inner_conn, altcp_mbedtls_lower_poll, interval);
+ }
+}
+
+static void
+altcp_mbedtls_recved(struct altcp_pcb *conn, u16_t len)
+{
+ u16_t lower_recved;
+ altcp_mbedtls_state_t *state;
+ if (conn == NULL) {
+ return;
+ }
+ state = (altcp_mbedtls_state_t *)conn->state;
+ if (state == NULL) {
+ return;
+ }
+ if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
+ return;
+ }
+ lower_recved = len;
+ if (lower_recved > state->rx_passed_unrecved) {
+ TRANSPORT_DEBUGF( ("bogus recved count (len > state->rx_passed_unrecved / %d / %d)",
+ len, state->rx_passed_unrecved));
+ lower_recved = (u16_t)state->rx_passed_unrecved;
+ }
+ state->rx_passed_unrecved -= lower_recved;
+
+ altcp_recved(conn->inner_conn, lower_recved);
+}
+
+static err_t
+altcp_mbedtls_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected)
+{
+ if (conn == NULL) {
+ return ERR_VAL;
+ }
+ conn->connected = connected;
+ return altcp_connect(conn->inner_conn, ipaddr, port, altcp_mbedtls_lower_connected);
+}
+
+static struct altcp_pcb *
+altcp_mbedtls_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err)
+{
+ struct altcp_pcb *lpcb;
+ if (conn == NULL) {
+ return NULL;
+ }
+ lpcb = altcp_listen_with_backlog_and_err(conn->inner_conn, backlog, err);
+ if (lpcb != NULL) {
+ conn->inner_conn = lpcb;
+ altcp_accept(lpcb, altcp_mbedtls_lower_accept);
+ return conn;
+ }
+ return NULL;
+}
+
+static void
+altcp_mbedtls_abort(struct altcp_pcb *conn)
+{
+ if (conn != NULL) {
+ altcp_abort(conn->inner_conn);
+ }
+}
+
+static err_t
+altcp_mbedtls_close(struct altcp_pcb *conn)
+{
+ struct altcp_pcb *inner_conn;
+ if (conn == NULL) {
+ return ERR_VAL;
+ }
+ inner_conn = conn->inner_conn;
+ if (inner_conn) {
+ err_t err;
+ altcp_poll_fn oldpoll = inner_conn->poll;
+ altcp_mbedtls_remove_callbacks(conn->inner_conn);
+ err = altcp_close(conn->inner_conn);
+ if (err != ERR_OK) {
+ /* not closed, set up all callbacks again */
+ altcp_mbedtls_setup_callbacks(conn, inner_conn);
+ /* poll callback is not included in the above */
+ altcp_poll(inner_conn, oldpoll, inner_conn->pollinterval);
+ return err;
+ }
+ conn->inner_conn = NULL;
+ }
+ altcp_free(conn);
+ return ERR_OK;
+}
+
+/** Allow caller of altcp_write() to limit to negotiated chunk size
+ * or remaining sndbuf space of inner_conn.
+ */
+static u16_t
+altcp_mbedtls_sndbuf(struct altcp_pcb *conn)
+{
+ if (conn) {
+ altcp_mbedtls_state_t *state;
+ state = (altcp_mbedtls_state_t*)conn->state;
+ if (!state || !(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
+ return 0;
+ }
+ if (conn->inner_conn) {
+ u16_t sndbuf = altcp_sndbuf(conn->inner_conn);
+ /* Take care of record header, IV, AuthTag */
+ int ssl_expan = mbedtls_ssl_get_record_expansion(&state->ssl_context);
+ if (ssl_expan > 0) {
+ size_t ssl_added = (u16_t)TRANSPORT_MIN(ssl_expan, 0xFFFF);
+ /* internal sndbuf smaller than our offset */
+ if (ssl_added < sndbuf) {
+ size_t max_len = 0xFFFF;
+ size_t ret;
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ /* @todo: adjust ssl_added to real value related to negociated cipher */
+ size_t max_frag_len_in = mbedtls_ssl_get_input_max_frag_len(&state->ssl_context);
+ size_t max_frag_len_out = mbedtls_ssl_get_output_max_frag_len(&state->ssl_context);
+
+ max_len = TRANSPORT_MIN(TRANSPORT_MIN(max_frag_len_in,max_frag_len_out), max_len);
+#endif
+ /* Adjust sndbuf of inner_conn with what added by SSL */
+ ret = TRANSPORT_MIN(sndbuf - ssl_added, max_len);
+ TRANSPORT_ASSERT("sndbuf overflow", ret <= 0xFFFF);
+ return (u16_t)ret;
+ }
+ }
+ }
+ }
+ /* fallback: use sendbuf of the inner connection */
+ return altcp_default_sndbuf(conn);
+}
+
+/** Write data to a TLS connection. Calls into mbedTLS, which in turn calls into
+ * @ref altcp_mbedtls_bio_send() to send the encrypted data
+ */
+static err_t
+altcp_mbedtls_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags)
+{
+ int ret;
+ altcp_mbedtls_state_t *state;
+
+ TRANSPORT_UNUSED_ARG(apiflags);
+
+ if (conn == NULL) {
+ return ERR_VAL;
+ }
+
+ state = (altcp_mbedtls_state_t *)conn->state;
+ if (state == NULL) {
+ /* @todo: which error? */
+ return ERR_CLSD;
+ }
+ if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) {
+ /* @todo: which error? */
+ return ERR_VAL;
+ }
+
+ /* HACK: if thre is something left to send, try to flush it and only
+ allow sending more if this succeeded (this is a hack because neither
+ returning 0 nor MBEDTLS_ERR_SSL_WANT_WRITE worked for me) */
+ if (state->ssl_context.out_left) {
+ ret = mbedtls_ssl_flush_output(&state->ssl_context);
+ if(ret != 0){
+ TRANSPORT_DEBUGF(("mbedtls_ssl_flash_output failed\n"));
+ return ret;
+ }
+ else if (state->ssl_context.out_left) {
+ return ERR_MEM;
+ }
+ }
+ ret = mbedtls_ssl_write(&state->ssl_context, (const unsigned char *)dataptr, len);
+ /* try to send data... */
+ altcp_output(conn->inner_conn);
+ if (ret >= 0) {
+ if (ret == len) {
+ state->flags |= ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT;
+ return ERR_OK;
+ } else {
+ /* @todo/@fixme: assumption: either everything sent or error */
+ TRANSPORT_ASSERT("ret <= 0", 0);
+ return ERR_MEM;
+ }
+ } else {
+ if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
+ /* @todo: convert error to err_t */
+ return ERR_MEM;
+ }
+ TRANSPORT_ASSERT("unhandled error", 0);
+ return ERR_VAL;
+ }
+}
+
+/** Send callback function called from mbedtls (set via mbedtls_ssl_set_bio)
+ * This function is either called during handshake or when sending application
+ * data via @ref altcp_mbedtls_write (or altcp_write)
+ */
+static int
+altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size)
+{
+ struct altcp_pcb *conn = (struct altcp_pcb *) ctx;
+ int written = 0;
+ size_t size_left = size;
+ u8_t apiflags = TCP_WRITE_FLAG_COPY;
+
+ TRANSPORT_ASSERT("conn != NULL", conn != NULL);
+ if ((conn == NULL) || (conn->inner_conn == NULL)) {
+ return MBEDTLS_ERR_NET_INVALID_CONTEXT;
+ }
+
+ while (size_left) {
+ u16_t write_len = (u16_t)TRANSPORT_MIN(size_left, 0xFFFF);
+ err_t err = altcp_write(conn->inner_conn, (const void *)dataptr, write_len, apiflags);
+ if (err == ERR_OK) {
+ written += write_len;
+ size_left -= write_len;
+ } else if (err == ERR_MEM) {
+ if (written) {
+ return written;
+ }
+ return 0; /* MBEDTLS_ERR_SSL_WANT_WRITE; */
+ } else {
+ TRANSPORT_ASSERT("tls_write, tcp_write: err != ERR MEM", 0);
+ /* @todo: return MBEDTLS_ERR_NET_CONN_RESET or MBEDTLS_ERR_NET_SEND_FAILED */
+ return MBEDTLS_ERR_NET_SEND_FAILED;
+ }
+ }
+ return written;
+}
+
+static u16_t
+altcp_mbedtls_mss(struct altcp_pcb *conn)
+{
+ if (conn == NULL) {
+ return 0;
+ }
+ /* @todo: TRANSPORT_MIN(mss, mbedtls_ssl_get_max_frag_len()) ? */
+ return altcp_mss(conn->inner_conn);
+}
+
+static void
+altcp_mbedtls_dealloc(struct altcp_pcb *conn)
+{
+ /* clean up and free tls state */
+ if (conn) {
+ altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
+ if (state) {
+ mbedtls_ssl_free(&state->ssl_context);
+ state->flags = 0;
+ if (state->rx) {
+ /* free leftover (unhandled) rx pbufs */
+ pbuf_free(state->rx);
+ state->rx = NULL;
+ }
+ altcp_mbedtls_free(state->conf, state);
+ conn->state = NULL;
+ }
+ }
+}
+
+const struct altcp_functions altcp_mbedtls_functions = {
+ altcp_mbedtls_set_poll,
+ altcp_mbedtls_recved,
+ altcp_default_bind,
+ altcp_mbedtls_connect,
+ altcp_mbedtls_listen,
+ altcp_mbedtls_abort,
+ altcp_mbedtls_close,
+ altcp_default_shutdown,
+ altcp_mbedtls_write,
+ altcp_default_output,
+ altcp_mbedtls_mss,
+ altcp_mbedtls_sndbuf,
+ altcp_default_sndqueuelen,
+ altcp_default_nagle_disable,
+ altcp_default_nagle_enable,
+ altcp_default_nagle_disabled,
+ altcp_default_setprio,
+ altcp_mbedtls_dealloc,
+ altcp_default_get_tcp_addrinfo,
+ altcp_default_get_ip,
+ altcp_default_get_port
+#ifdef ALTCP_DEBUG
+ , altcp_default_dbg_get_tcp_state
+#endif
+};
+
+#endif /* TRANSPORT_ALTCP_TLS && TRANSPORT_ALTCP_TLS_MBEDTLS */
+#endif /* TRANSPORT_ALTCP */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_tls_mbedtls_mem.c b/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_tls_mbedtls_mem.c
new file mode 100644
index 00000000000000..ce3a80940511b8
--- /dev/null
+++ b/third_party/silabs/mqtt/mqtt_transport_interface/src/altcp_tls_mbedtls_mem.c
@@ -0,0 +1,215 @@
+/**
+ * @file
+ * Application layered TCP connection API (to be used from TCPIP thread)
+ *
+ * This file contains memory management functions for a TLS layer using mbedTLS.
+ *
+ * ATTENTION: For production usage, you might want to override this file with
+ * your own implementation since this implementation simply uses the
+ * lwIP heap without caring for fragmentation or leaving heap for
+ * other parts of lwIP!
+ */
+
+/*
+ * Copyright (c) 2017 Simon Goldschmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Simon Goldschmidt
+ *
+ * Missing things / @todo:
+ * - RX data is acknowledged after receiving (tcp_recved is called when enqueueing
+ * the pbuf for mbedTLS receive, not when processed by mbedTLS or the inner
+ * connection; altcp_recved() from inner connection does nothing)
+ * - TX data is marked as 'sent' (i.e. acknowledged; sent callback is called) right
+ * after enqueueing for transmission, not when actually ACKed be the remote host.
+ */
+
+#include "altcp_opt.h"
+
+#if TRANSPORT_ALTCP /* don't build if not configured for use in lwipopts.h */
+
+#include "altcp_tls_mbedtls_opts.h"
+
+#if TRANSPORT_ALTCP_TLS && TRANSPORT_ALTCP_TLS_MBEDTLS
+
+#include "altcp_tls_mbedtls_mem.h"
+#include "altcp_tls_mbedtls_structs.h"
+
+#include "mbedtls/platform.h"
+
+#include
+
+#ifndef ALTCP_MBEDTLS_MEM_DEBUG
+#define ALTCP_MBEDTLS_MEM_DEBUG LWIP_DBG_OFF
+#endif
+
+#if defined(MBEDTLS_PLATFORM_MEMORY) && \
+ (!defined(MBEDTLS_PLATFORM_FREE_MACRO) || \
+ defined(MBEDTLS_PLATFORM_CALLOC_MACRO))
+#define ALTCP_MBEDTLS_PLATFORM_ALLOC 1
+#else
+#define ALTCP_MBEDTLS_PLATFORM_ALLOC 0
+#endif
+
+#if ALTCP_MBEDTLS_PLATFORM_ALLOC
+
+#ifndef ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS
+#define ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS 0
+#endif
+
+/* This is an example/debug implementation of alloc/free functions only */
+typedef struct altcp_mbedtls_malloc_helper_s {
+ size_t c;
+ size_t len;
+} altcp_mbedtls_malloc_helper_t;
+
+#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS
+typedef struct altcp_mbedtls_malloc_stats_s {
+ size_t allocedBytes;
+ size_t allocCnt;
+ size_t maxBytes;
+ size_t totalBytes;
+} altcp_mbedtls_malloc_stats_t;
+altcp_mbedtls_malloc_stats_t altcp_mbedtls_malloc_stats;
+volatile int altcp_mbedtls_malloc_clear_stats;
+#endif
+
+static void *
+tls_malloc(size_t c, size_t len)
+{
+ altcp_mbedtls_malloc_helper_t *hlpr;
+ void *ret;
+ size_t alloc_size;
+#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS
+ if (altcp_mbedtls_malloc_clear_stats) {
+ altcp_mbedtls_malloc_clear_stats = 0;
+ memset(&altcp_mbedtls_malloc_stats, 0, sizeof(altcp_mbedtls_malloc_stats));
+ }
+#endif
+ alloc_size = sizeof(altcp_mbedtls_malloc_helper_t) + (c * len);
+ /* check for maximum allocation size, mainly to prevent mem_size_t overflow */
+ #if 0
+ if (alloc_size > MEM_SIZE) {
+ TRANSPORT_DEBUGF( ("mbedtls allocation too big: %c * %d bytes vs MEM_SIZE=%d",
+ (int)c, (int)len, (int)MEM_SIZE));
+ return NULL;
+ }
+ #endif
+ hlpr = (altcp_mbedtls_malloc_helper_t *)pvPortMalloc((mem_size_t)alloc_size);
+ if (hlpr == NULL) {
+ TRANSPORT_DEBUGF( ("mbedtls alloc callback failed for %c * %d bytes", (int)c, (int)len));
+ return NULL;
+ }
+#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS
+ altcp_mbedtls_malloc_stats.allocCnt++;
+ altcp_mbedtls_malloc_stats.allocedBytes += c * len;
+ if (altcp_mbedtls_malloc_stats.allocedBytes > altcp_mbedtls_malloc_stats.maxBytes) {
+ altcp_mbedtls_malloc_stats.maxBytes = altcp_mbedtls_malloc_stats.allocedBytes;
+ }
+ altcp_mbedtls_malloc_stats.totalBytes += c * len;
+#endif
+ hlpr->c = c;
+ hlpr->len = len;
+ ret = hlpr + 1;
+ /* zeroing the allocated chunk is required by mbedTLS! */
+ memset(ret, 0, c * len);
+ return ret;
+}
+
+static void
+tls_free(void *ptr)
+{
+ altcp_mbedtls_malloc_helper_t *hlpr;
+ if (ptr == NULL) {
+ /* this obviously happened in mbedtls... */
+ return;
+ }
+ hlpr = ((altcp_mbedtls_malloc_helper_t *)ptr) - 1;
+#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS
+ if (!altcp_mbedtls_malloc_clear_stats) {
+ altcp_mbedtls_malloc_stats.allocedBytes -= hlpr->c * hlpr->len;
+ }
+#endif
+ vPortFree(hlpr);
+}
+#endif /* ALTCP_MBEDTLS_PLATFORM_ALLOC*/
+
+void
+altcp_mbedtls_mem_init(void)
+{
+ /* not much to do here when using the heap */
+
+#if ALTCP_MBEDTLS_PLATFORM_ALLOC
+ /* set mbedtls allocation methods */
+ mbedtls_platform_set_calloc_free(&tls_malloc, &tls_free);
+#endif
+}
+
+altcp_mbedtls_state_t *
+altcp_mbedtls_alloc(void *conf)
+{
+ altcp_mbedtls_state_t *ret = (altcp_mbedtls_state_t *)pvPortMalloc(sizeof(altcp_mbedtls_state_t));
+ if (ret != NULL) {
+ memset(ret, 0x00, sizeof(altcp_mbedtls_state_t));
+ ret->conf = conf;
+ }
+ return ret;
+}
+
+void
+altcp_mbedtls_free(void *conf, altcp_mbedtls_state_t *state)
+{
+ TRANSPORT_UNUSED_ARG(conf);
+ TRANSPORT_ASSERT("state != NULL", state != NULL);
+ vPortFree(state);
+}
+
+void *
+altcp_mbedtls_alloc_config(size_t size)
+{
+ void *ret;
+ size_t checked_size = (mem_size_t)size;
+ if (size != checked_size) {
+ /* allocation too big (mem_size_t overflow) */
+ return NULL;
+ }
+ ret = (altcp_mbedtls_state_t *)pvPortMalloc((mem_size_t)size);
+ if(ret != NULL){
+ memset(ret, 0x00, sizeof(altcp_mbedtls_state_t));
+ }
+ return ret;
+}
+
+void
+altcp_mbedtls_free_config(void *item)
+{
+ TRANSPORT_ASSERT("item != NULL", item != NULL);
+ vPortFree(item);
+}
+
+#endif /* TRANSPORT_ALTCP_TLS && TRANSPORT_ALTCP_TLS_MBEDTLS */
+#endif /* TRANSPORT_ALTCP */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/stack/mqtt.c b/third_party/silabs/mqtt/stack/mqtt.c
new file mode 100644
index 00000000000000..db039a380c7f59
--- /dev/null
+++ b/third_party/silabs/mqtt/stack/mqtt.c
@@ -0,0 +1,1275 @@
+/**
+ * @file
+ * MQTT client
+ *
+ * @defgroup mqtt MQTT client
+ * @ingroup apps
+ * @verbinclude mqtt_client.txt
+ */
+
+/*
+ * Copyright (c) 2016 Erik Andersson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack
+ *
+ * Author: Erik Andersson
+ *
+ *
+ * @todo:
+ * - Handle large outgoing payloads for PUBLISH messages
+ * - Fix restriction of a single topic in each (UN)SUBSCRIBE message (protocol has support for multiple topics)
+ * - Add support for legacy MQTT protocol version
+ *
+ * Please coordinate changes and requests with Erik Andersson
+ * Erik Andersson
+ *
+ */
+#include "mqtt.h"
+#include
+
+/**
+ * MQTT_DEBUG: Default is off.
+ */
+#if !defined MQTT_DEBUG || defined __DOXYGEN__
+#define MQTT_DEBUG 0x00
+#endif
+#if !defined MQTT_ASSERT_CORE_LOCKED || defined __DOXYGEN__
+#define MQTT_ASSERT_CORE_LOCKED()
+#endif
+extern void *mem_calloc(mqtt_mem_size_t count, mqtt_mem_size_t size);
+extern void mem_free(void *mem);
+
+mqtt_connection_status_t
+mqtt_parse_incoming(mqtt_client_t *client);
+void
+mqtt_output_send(struct mqtt_ringbuf_t *rb, mqtt_transport_intf_t *trans);
+
+#ifdef MQTT_DEBUG
+extern void efr32Log(const char * aFormat, ...);
+#define MQTT_DEBUGF(x) efr32Log x;
+#else
+#define MQTT_DEBUGF(x)
+#endif
+
+/**
+ * MQTT control message types
+ */
+enum mqtt_message_type {
+ MQTT_MSG_TYPE_CONNECT = 1,
+ MQTT_MSG_TYPE_CONNACK = 2,
+ MQTT_MSG_TYPE_PUBLISH = 3,
+ MQTT_MSG_TYPE_PUBACK = 4,
+ MQTT_MSG_TYPE_PUBREC = 5,
+ MQTT_MSG_TYPE_PUBREL = 6,
+ MQTT_MSG_TYPE_PUBCOMP = 7,
+ MQTT_MSG_TYPE_SUBSCRIBE = 8,
+ MQTT_MSG_TYPE_SUBACK = 9,
+ MQTT_MSG_TYPE_UNSUBSCRIBE = 10,
+ MQTT_MSG_TYPE_UNSUBACK = 11,
+ MQTT_MSG_TYPE_PINGREQ = 12,
+ MQTT_MSG_TYPE_PINGRESP = 13,
+ MQTT_MSG_TYPE_DISCONNECT = 14
+};
+
+/** Helpers to extract control packet type and qos from first byte in fixed header */
+#define MQTT_CTL_PACKET_TYPE(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0xf0) >> 4)
+#define MQTT_CTL_PACKET_QOS(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0x6) >> 1)
+
+/**
+ * MQTT connect flags, only used in CONNECT message
+ */
+enum mqtt_connect_flag {
+ MQTT_CONNECT_FLAG_USERNAME = 1 << 7,
+ MQTT_CONNECT_FLAG_PASSWORD = 1 << 6,
+ MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5,
+ MQTT_CONNECT_FLAG_WILL = 1 << 2,
+ MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1
+};
+
+
+static void mqtt_cyclic_timer(void *arg);
+
+
+static const char *const mqtt_message_type_str[15] = {
+ "UNDEFINED",
+ "CONNECT",
+ "CONNACK",
+ "PUBLISH",
+ "PUBACK",
+ "PUBREC",
+ "PUBREL",
+ "PUBCOMP",
+ "SUBSCRIBE",
+ "SUBACK",
+ "UNSUBSCRIBE",
+ "UNSUBACK",
+ "PINGREQ",
+ "PINGRESP",
+ "DISCONNECT"
+};
+
+/**
+ * Message type value to string
+ * @param msg_type see enum mqtt_message_type
+ *
+ * @return Control message type text string
+ */
+static const char *
+mqtt_msg_type_to_str(uint8_t msg_type)
+{
+ if (msg_type >= MQTT_ARRAYSIZE(mqtt_message_type_str)) {
+ msg_type = 0;
+ }
+ return mqtt_message_type_str[msg_type];
+}
+
+
+/**
+ * Generate MQTT packet identifier
+ * @param client MQTT client
+ * @return New packet identifier, range 1 to 65535
+ */
+static uint16_t
+msg_generate_packet_id(mqtt_client_t *client)
+{
+ client->pkt_id_seq++;
+ if (client->pkt_id_seq == 0) {
+ client->pkt_id_seq++;
+ }
+ return client->pkt_id_seq;
+}
+
+/**
+ * Try send as many bytes as possible from output ring buffer
+ * @param rb Output ring buffer
+ * @param tpcb TCP connection handle
+ */
+
+
+/*--------------------------------------------------------------------------------------------------------------------- */
+/* Request queue */
+
+/**
+ * Create request item
+ * @param r_objs Pointer to request objects
+ * @param r_objs_len Number of array entries
+ * @param pkt_id Packet identifier of request
+ * @param cb Packet callback to call when requests lifetime ends
+ * @param arg Parameter following callback
+ * @return Request or NULL if failed to create
+ */
+static struct mqtt_request_t *
+mqtt_create_request(struct mqtt_request_t *r_objs, size_t r_objs_len, uint16_t pkt_id, mqtt_request_cb_t cb, void *arg)
+{
+ struct mqtt_request_t *r = NULL;
+ uint8_t n;
+ MQTT_ASSERT("mqtt_create_request: r_objs != NULL", r_objs != NULL);
+ for (n = 0; n < r_objs_len; n++) {
+ /* Item point to itself if not in use */
+ if (r_objs[n].next == &r_objs[n]) {
+ r = &r_objs[n];
+ r->next = NULL;
+ r->cb = cb;
+ r->arg = arg;
+ r->pkt_id = pkt_id;
+ break;
+ }
+ }
+ return r;
+}
+
+
+/**
+ * Append request to pending request queue
+ * @param tail Pointer to request queue tail pointer
+ * @param r Request to append
+ */
+static void
+mqtt_append_request(struct mqtt_request_t **tail, struct mqtt_request_t *r)
+{
+ struct mqtt_request_t *head = NULL;
+ int16_t time_before = 0;
+ struct mqtt_request_t *iter;
+
+ MQTT_ASSERT("mqtt_append_request: tail != NULL", tail != NULL);
+
+ /* Iterate trough queue to find head, and count total timeout time */
+ for (iter = *tail; iter != NULL; iter = iter->next) {
+ time_before += iter->timeout_diff;
+ head = iter;
+ }
+
+ MQTT_ASSERT("mqtt_append_request: time_before <= MQTT_REQ_TIMEOUT", time_before <= MQTT_REQ_TIMEOUT);
+ r->timeout_diff = MQTT_REQ_TIMEOUT - time_before;
+ if (head == NULL) {
+ *tail = r;
+ } else {
+ head->next = r;
+ }
+}
+
+
+/**
+ * Delete request item
+ * @param r Request item to delete
+ */
+void
+mqtt_delete_request(struct mqtt_request_t *r)
+{
+ if (r != NULL) {
+ r->next = r;
+ }
+}
+
+/**
+ * Remove a request item with a specific packet identifier from request queue
+ * @param tail Pointer to request queue tail pointer
+ * @param pkt_id Packet identifier of request to take
+ * @return Request item if found, NULL if not
+ */
+struct mqtt_request_t *
+mqtt_take_request(struct mqtt_request_t **tail, uint16_t pkt_id)
+{
+ struct mqtt_request_t *iter = NULL, *prev = NULL;
+ MQTT_ASSERT("mqtt_take_request: tail != NULL", tail != NULL);
+ /* Search all request for pkt_id */
+ for (iter = *tail; iter != NULL; iter = iter->next) {
+ if (iter->pkt_id == pkt_id) {
+ break;
+ }
+ prev = iter;
+ }
+
+ /* If request was found */
+ if (iter != NULL) {
+ /* unchain */
+ if (prev == NULL) {
+ *tail = iter->next;
+ } else {
+ prev->next = iter->next;
+ }
+ /* If exists, add remaining timeout time for the request to next */
+ if (iter->next != NULL) {
+ iter->next->timeout_diff += iter->timeout_diff;
+ }
+ iter->next = NULL;
+ }
+ return iter;
+}
+
+/**
+ * Handle requests timeout
+ * @param tail Pointer to request queue tail pointer
+ * @param t Time since last call in seconds
+ */
+static void
+mqtt_request_time_elapsed(struct mqtt_request_t **tail, uint8_t t)
+{
+ struct mqtt_request_t *r;
+ MQTT_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL);
+ r = *tail;
+ while (t > 0 && r != NULL) {
+ if (t >= r->timeout_diff) {
+ t -= (uint8_t)r->timeout_diff;
+ /* Unchain */
+ *tail = r->next;
+ /* Notify upper layer about timeout */
+ if (r->cb != NULL) {
+ r->cb(r->arg, MQTT_ERR_TIMEOUT);
+ }
+ mqtt_delete_request(r);
+ /* Tail might be be modified in callback, so re-read it in every iteration */
+ r = *(struct mqtt_request_t *const volatile *)tail;
+ } else {
+ r->timeout_diff -= t;
+ t = 0;
+ }
+ }
+}
+
+/**
+ * Free all request items
+ * @param tail Pointer to request queue tail pointer
+ */
+static void
+mqtt_clear_requests(struct mqtt_request_t **tail)
+{
+ struct mqtt_request_t *iter, *next;
+ MQTT_ASSERT("mqtt_clear_requests: tail != NULL", tail != NULL);
+ for (iter = *tail; iter != NULL; iter = next) {
+ next = iter->next;
+ mqtt_delete_request(iter);
+ }
+ *tail = NULL;
+}
+
+/**
+ * Initialize all request items
+ * @param r_objs Pointer to request objects
+ * @param r_objs_len Number of array entries
+ */
+static void
+mqtt_init_requests(struct mqtt_request_t *r_objs, size_t r_objs_len)
+{
+ uint8_t n;
+ MQTT_ASSERT("mqtt_init_requests: r_objs != NULL", r_objs != NULL);
+ for (n = 0; n < r_objs_len; n++) {
+ /* Item pointing to itself indicates unused */
+ r_objs[n].next = &r_objs[n];
+ }
+}
+
+/*--------------------------------------------------------------------------------------------------------------------- */
+/* Output message build helpers */
+
+static void
+mqtt_output_append_uint8(struct mqtt_ringbuf_t *rb, uint8_t value)
+{
+ mqtt_ringbuf_put(rb, value);
+}
+
+static
+void mqtt_output_append_uint16(struct mqtt_ringbuf_t *rb, uint16_t value)
+{
+ mqtt_ringbuf_put(rb, value >> 8);
+ mqtt_ringbuf_put(rb, value & 0xff);
+}
+
+static void
+mqtt_output_append_buf(struct mqtt_ringbuf_t *rb, const void *data, uint16_t length)
+{
+ uint16_t n;
+ for (n = 0; n < length; n++) {
+ mqtt_ringbuf_put(rb, ((const uint8_t *)data)[n]);
+ }
+}
+
+static void
+mqtt_output_append_string(struct mqtt_ringbuf_t *rb, const char *str, uint16_t length)
+{
+ uint16_t n;
+ mqtt_ringbuf_put(rb, length >> 8);
+ mqtt_ringbuf_put(rb, length & 0xff);
+ for (n = 0; n < length; n++) {
+ mqtt_ringbuf_put(rb, str[n]);
+ }
+}
+
+/**
+ * Append fixed header
+ * @param rb Output ring buffer
+ * @param msg_type see enum mqtt_message_type
+ * @param fdup MQTT DUP flag
+ * @param fqos MQTT QoS field
+ * @param fretain MQTT retain flag
+ * @param r_length Remaining length after fixed header
+ */
+
+static void
+mqtt_output_append_fixed_header(struct mqtt_ringbuf_t *rb, uint8_t msg_type, uint8_t fdup,
+ uint8_t fqos, uint8_t fretain, uint16_t r_length)
+{
+ /* Start with control byte */
+ mqtt_output_append_uint8(rb, (((msg_type & 0x0f) << 4) | ((fdup & 1) << 3) | ((fqos & 3) << 1) | (fretain & 1)));
+ /* Encode remaining length field */
+ do {
+ mqtt_output_append_uint8(rb, (r_length & 0x7f) | (r_length >= 128 ? 0x80 : 0));
+ r_length >>= 7;
+ } while (r_length > 0);
+}
+
+/**
+ * Check output buffer space
+ * @param rb Output ring buffer
+ * @param r_length Remaining length after fixed header
+ * @return 1 if message will fit, 0 if not enough buffer space
+ */
+static uint8_t
+mqtt_output_check_space(struct mqtt_ringbuf_t *rb, uint16_t r_length)
+{
+ /* Start with length of type byte + remaining length */
+ uint16_t total_len = 1 + r_length;
+
+ MQTT_ASSERT("mqtt_output_check_space: rb != NULL", rb != NULL);
+
+ /* Calculate number of required bytes to contain the remaining bytes field and add to total*/
+ do {
+ total_len++;
+ r_length >>= 7;
+ } while (r_length > 0);
+
+ return (total_len <= mqtt_ringbuf_free(rb));
+}
+
+
+/**
+ * Close connection to server
+ * @param client MQTT client
+ * @param reason Reason for disconnection
+ */
+void
+mqtt_close(mqtt_client_t *client, mqtt_connection_status_t reason)
+{
+ MQTT_ASSERT("mqtt_close: client != NULL", client != NULL);
+
+ client->conn->close_connection(client->conn->connCtxt);
+
+ /* Remove all pending requests */
+ mqtt_clear_requests(&client->pend_req_queue);
+ /* Stop cyclic timer */
+ client->conn->timer_stop(mqtt_cyclic_timer, client);
+ client->conn = NULL;
+
+ /* Notify upper layer of disconnection if changed state */
+ if (client->conn_state != TCP_DISCONNECTED) {
+
+ client->conn_state = TCP_DISCONNECTED;
+ if (client->connect_cb != NULL) {
+ client->connect_cb(client, client->connect_arg, reason);
+ }
+ }
+}
+
+static mqtt_err_t mqtt_process_rx(mqtt_client_t *client)
+{
+ mqtt_connection_status_t res;
+
+ if (MQTT_CONNECT_ACCEPTED != (res = mqtt_parse_incoming(client))) {
+ MQTT_DEBUGF (("mqtt_parse - %u", res));
+ mqtt_close(client, res);
+ return res;
+ }
+ /* If keep alive functionality is used */
+ if (client->keep_alive != 0) {
+ /* Reset server alive watchdog */
+ client->server_watchdog = 0;
+ }
+ return MQTT_CONNECT_ACCEPTED;
+}
+
+static void mqtt_process_tx(mqtt_client_t *client, uint8_t isTxDone)
+{
+ struct mqtt_request_t *r;
+
+ if (client->conn_state != MQTT_CONNECTED) return;
+
+ if (isTxDone)
+ {
+ client->cyclic_tick = 0;
+ client->server_watchdog = 0;
+
+ /* QoS 0 publish has no response from server, so call its callbacks here */
+ while ((r = mqtt_take_request(&client->pend_req_queue, 0)) != NULL) {
+ MQTT_DEBUGF(("mqtt_tcp_sent_cb: Calling QoS 0 publish complete callback\n"));
+ if (r->cb != NULL) {
+ r->cb(r->arg, MQTT_ERR_OK);
+ }
+ mqtt_delete_request(r);
+ }
+ }
+ /* Try send any remaining buffers from output queue */
+ mqtt_output_send(&client->output, client->conn);
+}
+
+/**
+ * Process async events such as receive response or send pending request on buffer availability
+ * @param client mqtt client handle
+*/
+void mqtt_process(mqtt_client_t *client, uint8_t isTxDone)
+{
+ if (!isTxDone && (MQTT_CONNECT_ACCEPTED != mqtt_process_rx(client)))
+ return;
+ mqtt_process_tx(client, isTxDone);
+ return;
+}
+
+/**
+ * Try send as many bytes as possible from output ring buffer
+ * @param rb Output ring buffer
+ * @param tpcb TCP connection handle
+ */
+void
+mqtt_output_send(struct mqtt_ringbuf_t *rb, mqtt_transport_intf_t *trans)
+{
+ mqtt_err_t err;
+ uint8_t wrap = 0;
+ uint16_t ringbuf_lin_len = mqtt_ringbuf_linear_read_length(rb);
+ uint16_t send_len = 0;
+ MQTT_ASSERT("mqtt_output_send: trans != NULL", trans != NULL);
+ MQTT_ASSERT("mqtt_output_send: trans->send_to_nw != NULL", trans->send_to_network != NULL);
+
+ if (trans->get_send_len)
+ {
+ send_len = trans->get_send_len(trans->connCtxt);
+ }
+ if (send_len == 0 || ringbuf_lin_len == 0) {
+ return;
+ }
+
+ MQTT_DEBUGF(("mqtt_output_send: tcp_sndbuf: %d bytes, ringbuf_linear_available: %d, get %d, put %d\n",send_len, ringbuf_lin_len, ((rb)->get & MQTT_RINGBUF_IDX_MASK), ((rb)->put & MQTT_RINGBUF_IDX_MASK)));
+
+ if (send_len > ringbuf_lin_len) {
+ /* Space in TCP output buffer is larger than available in ring buffer linear portion */
+ send_len = ringbuf_lin_len;
+ /* Wrap around if more data in ring buffer after linear portion */
+ wrap = (mqtt_ringbuf_len(rb) > ringbuf_lin_len);
+ }
+ err = trans->send_to_network(trans->connCtxt, mqtt_ringbuf_get_ptr(rb), send_len,
+ MQTT_WRITE_FLAG_COPY | (wrap ? MQTT_WRITE_FLAG_MORE : 0), !wrap);
+ if ((err == MQTT_ERR_OK) && wrap) {
+ mqtt_ringbuf_advance_get_idx(rb, send_len);
+ /* Use the lesser one of ring buffer linear length and TCP send buffer size */
+ if (trans->get_send_len)
+ send_len = trans->get_send_len(trans->connCtxt);
+ else
+ send_len = 0;
+ send_len = MQTT_MIN(send_len, mqtt_ringbuf_linear_read_length(rb));
+ err = trans->send_to_network(trans->connCtxt, mqtt_ringbuf_get_ptr(rb), send_len, MQTT_WRITE_FLAG_COPY, 1);
+ }
+ if (err == MQTT_ERR_OK) {
+ mqtt_ringbuf_advance_get_idx(rb, send_len);
+ } else {
+ MQTT_DEBUGF(("mqtt_output_send: Send failed with err %d \n", err));
+ }
+}
+
+/**
+ * Interval timer, called every MQTT_CYCLIC_TIMER_INTERVAL seconds in MQTT_CONNECTING and MQTT_CONNECTED states
+ * @param arg MQTT client
+ */
+void
+mqtt_cyclic_timer(void *arg)
+{
+ uint8_t restart_timer = 1;
+ mqtt_client_t *client = (mqtt_client_t *)arg;
+ MQTT_ASSERT("mqtt_cyclic_timer: client != NULL", client != NULL);
+
+ if (client->conn_state == MQTT_CONNECTING) {
+ client->cyclic_tick++;
+ if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= MQTT_CONNECT_TIMOUT) {
+ MQTT_DEBUGF(("mqtt_cyclic_timer: CONNECT attempt to server timed out\n"));
+ /* Disconnect TCP */
+ mqtt_close(client, MQTT_CONNECT_TIMEOUT);
+ restart_timer = 0;
+ }
+ } else if (client->conn_state == MQTT_CONNECTED) {
+ /* Handle timeout for pending requests */
+ mqtt_request_time_elapsed(&client->pend_req_queue, MQTT_CYCLIC_TIMER_INTERVAL);
+
+ /* keep_alive > 0 means keep alive functionality shall be used */
+ if (client->keep_alive > 0) {
+
+ client->server_watchdog++;
+ /* If reception from server has been idle for 1.5*keep_alive time, server is considered unresponsive */
+ if ((client->server_watchdog * MQTT_CYCLIC_TIMER_INTERVAL) > (client->keep_alive + client->keep_alive / 2)) {
+ MQTT_DEBUGF( ("mqtt_cyclic_timer: Server incoming keep-alive timeout\n"));
+ mqtt_close(client, MQTT_CONNECT_TIMEOUT);
+ restart_timer = 0;
+ }
+
+ /* If time for a keep alive message to be sent, transmission has been idle for keep_alive time */
+ if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= client->keep_alive) {
+ MQTT_DEBUGF(("mqtt_cyclic_timer: Sending keep-alive message to server\n"));
+ if (mqtt_output_check_space(&client->output, 0) != 0) {
+ mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0, 0);
+ client->cyclic_tick = 0;
+ }
+ } else {
+ client->cyclic_tick++;
+ }
+ }
+ } else {
+ MQTT_DEBUGF(("mqtt_cyclic_timer: Timer should not be running in state %d\n", client->conn_state));
+ restart_timer = 0;
+ }
+ if (restart_timer) {
+ client->conn->timer_start(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, arg);
+ }
+}
+
+
+/**
+ * Send PUBACK, PUBREC or PUBREL response message
+ * @param client MQTT client
+ * @param msg PUBACK, PUBREC or PUBREL
+ * @param pkt_id Packet identifier
+ * @param qos QoS value
+ * @return MQTT_ERR_OK if successful, MQTT_ERR_MEM if out of memory
+ */
+static mqtt_err_t
+pub_ack_rec_rel_response(mqtt_client_t *client, uint8_t msg, uint16_t pkt_id, uint8_t qos)
+{
+ mqtt_err_t err = MQTT_ERR_OK;
+ if (mqtt_output_check_space(&client->output, 2)) {
+ mqtt_output_append_fixed_header(&client->output, msg, 0, qos, 0, 2);
+ mqtt_output_append_uint16(&client->output, pkt_id);
+ mqtt_output_send(&client->output, client->conn);
+ } else {
+ MQTT_DEBUGF(("pub_ack_rec_rel_response: OOM creating response: %s with pkt_id: %d\n",mqtt_msg_type_to_str(msg), pkt_id));
+ err = MQTT_ERR_MEM;
+ }
+ return err;
+}
+
+/**
+ * Subscribe response from server
+ * @param r Matching request
+ * @param result Result code from server
+ */
+static void
+mqtt_incomming_suback(struct mqtt_request_t *r, uint8_t result)
+{
+ if (r->cb != NULL) {
+ r->cb(r->arg, result < 3 ? MQTT_ERR_OK : MQTT_ERR_ABRT);
+ }
+}
+
+
+/**
+ * Complete MQTT message received or buffer full
+ * @param client MQTT client
+ * @param fixed_hdr_idx header index
+ * @param length length received part
+ * @param remaining_length Remaining length of complete message
+ */
+mqtt_connection_status_t
+mqtt_message_received(mqtt_client_t *client, uint8_t fixed_hdr_idx, uint16_t length, uint32_t remaining_length)
+{
+ mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED;
+
+ uint8_t *var_hdr_payload = client->rx_buffer + fixed_hdr_idx;
+ size_t var_hdr_payload_bufsize = sizeof(client->rx_buffer) - fixed_hdr_idx;
+
+ /* Control packet type */
+ uint8_t pkt_type = MQTT_CTL_PACKET_TYPE(client->rx_buffer[0]);
+ uint16_t pkt_id = 0;
+
+ MQTT_ASSERT("client->msg_idx < MQTT_VAR_HEADER_BUFFER_LEN", client->msg_idx < MQTT_VAR_HEADER_BUFFER_LEN);
+ MQTT_ASSERT("fixed_hdr_idx <= client->msg_idx", fixed_hdr_idx <= client->msg_idx);
+ MQTT_ERROR("buffer length mismatch", fixed_hdr_idx + length <= MQTT_VAR_HEADER_BUFFER_LEN,
+ return MQTT_CONNECT_DISCONNECTED);
+
+ if (pkt_type == MQTT_MSG_TYPE_CONNACK) {
+ if (client->conn_state == MQTT_CONNECTING) {
+ if (length < 2) {
+ MQTT_DEBUGF(( "mqtt_message_received: Received short CONNACK message\n"));
+ goto out_disconnect;
+ }
+ /* Get result code from CONNACK */
+ res = (mqtt_connection_status_t)var_hdr_payload[1];
+ MQTT_DEBUGF(("mqtt_message_received: Connect response code %d\n", res));
+ if (res == MQTT_CONNECT_ACCEPTED) {
+ /* Reset cyclic_tick when changing to connected state */
+ client->cyclic_tick = 0;
+ client->conn_state = MQTT_CONNECTED;
+ /* Notify upper layer */
+ if (client->connect_cb != 0) {
+ client->connect_cb(client, client->connect_arg, res);
+ }
+ }
+ } else {
+ MQTT_DEBUGF(("mqtt_message_received: Received CONNACK in connected state\n"));
+ }
+ } else if (pkt_type == MQTT_MSG_TYPE_PINGRESP) {
+ MQTT_DEBUGF(( "mqtt_message_received: Received PINGRESP from server\n"));
+
+ } else if (pkt_type == MQTT_MSG_TYPE_PUBLISH) {
+ uint16_t payload_offset = 0;
+ uint16_t payload_length = length;
+ uint8_t qos = MQTT_CTL_PACKET_QOS(client->rx_buffer[0]);
+
+ if (client->msg_idx <= MQTT_VAR_HEADER_BUFFER_LEN) {
+ /* Should have topic and pkt id*/
+ uint8_t *topic;
+ uint16_t after_topic;
+ uint8_t bkp;
+ uint16_t topic_len;
+ uint16_t qos_len = (qos ? 2U : 0U);
+ if (length < 2 + qos_len) {
+ MQTT_DEBUGF(( "mqtt_message_received: Received short PUBLISH packet\n"));
+ goto out_disconnect;
+ }
+ topic_len = var_hdr_payload[0];
+ topic_len = (topic_len << 8) + (uint16_t)(var_hdr_payload[1]);
+ if ((topic_len > length - (2 + qos_len)) ||
+ (topic_len > var_hdr_payload_bufsize - (2 + qos_len))) {
+ MQTT_DEBUGF(( "mqtt_message_received: Received short PUBLISH packet (topic)\n"));
+ goto out_disconnect;
+ }
+
+ topic = var_hdr_payload + 2;
+ after_topic = 2 + topic_len;
+ /* Check buffer length, add one byte even for QoS 0 so that zero termination will fit */
+ if ((after_topic + (qos ? 2U : 1U)) > var_hdr_payload_bufsize) {
+ MQTT_DEBUGF(("mqtt_message_received: Receive buffer can not fit topic + pkt_id\n"));
+ goto out_disconnect;
+ }
+
+ /* id for QoS 1 and 2 */
+ if (qos > 0) {
+ if (length < after_topic + 2U) {
+ MQTT_DEBUGF(( "mqtt_message_received: Received short PUBLISH packet (after_topic)\n"));
+ goto out_disconnect;
+ }
+ client->inpub_pkt_id = ((uint16_t)var_hdr_payload[after_topic] << 8) + (uint16_t)var_hdr_payload[after_topic + 1];
+ after_topic += 2;
+ } else {
+ client->inpub_pkt_id = 0;
+ }
+ /* Take backup of byte after topic */
+ bkp = topic[topic_len];
+ /* Zero terminate string */
+ topic[topic_len] = 0;
+ /* Payload data remaining in receive buffer */
+ payload_length = length - after_topic;
+ payload_offset = after_topic;
+
+ MQTT_DEBUGF(("mqtt_incomming_publish: Received message with QoS %d at topic: %s, payload length %u\n",
+ qos, topic, remaining_length + payload_length));
+ if (client->pub_cb != NULL) {
+ client->pub_cb(client->inpub_arg, (const char *)topic, remaining_length + payload_length);
+ }
+ /* Restore byte after topic */
+ topic[topic_len] = bkp;
+ }
+ if (payload_length > 0 || remaining_length == 0) {
+ if (length < (size_t)(payload_offset + payload_length)) {
+ MQTT_DEBUGF(( "mqtt_message_received: Received short packet (payload)\n"));
+ goto out_disconnect;
+ }
+ client->data_cb(client->inpub_arg, var_hdr_payload + payload_offset, payload_length, remaining_length == 0 ? MQTT_DATA_FLAG_LAST : 0);
+ /* Reply if QoS > 0 */
+ if (remaining_length == 0 && qos > 0) {
+ /* Send PUBACK for QoS 1 or PUBREC for QoS 2 */
+ uint8_t resp_msg = (qos == 1) ? MQTT_MSG_TYPE_PUBACK : MQTT_MSG_TYPE_PUBREC;
+ MQTT_DEBUGF(("mqtt_incomming_publish: Sending publish response: %s with pkt_id: %d\n",
+ mqtt_msg_type_to_str(resp_msg), client->inpub_pkt_id));
+ pub_ack_rec_rel_response(client, resp_msg, client->inpub_pkt_id, 0);
+ }
+ }
+ } else {
+ /* Get packet identifier */
+ pkt_id = (uint16_t)var_hdr_payload[0] << 8;
+ pkt_id |= (uint16_t)var_hdr_payload[1];
+ if (pkt_id == 0) {
+ MQTT_DEBUGF(("mqtt_message_received: Got message with illegal packet identifier: 0\n"));
+ goto out_disconnect;
+ }
+ if (pkt_type == MQTT_MSG_TYPE_PUBREC) {
+ MQTT_DEBUGF(("mqtt_message_received: PUBREC, sending PUBREL with pkt_id: %d\n", pkt_id));
+ pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBREL, pkt_id, 1);
+
+ } else if (pkt_type == MQTT_MSG_TYPE_PUBREL) {
+ MQTT_DEBUGF(("mqtt_message_received: PUBREL, sending PUBCOMP response with pkt_id: %d\n", pkt_id));
+ pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBCOMP, pkt_id, 0);
+
+ } else if (pkt_type == MQTT_MSG_TYPE_SUBACK || pkt_type == MQTT_MSG_TYPE_UNSUBACK ||
+ pkt_type == MQTT_MSG_TYPE_PUBCOMP || pkt_type == MQTT_MSG_TYPE_PUBACK) {
+ struct mqtt_request_t *r = mqtt_take_request(&client->pend_req_queue, pkt_id);
+ if (r != NULL) {
+ MQTT_DEBUGF(("mqtt_message_received: %s response with id %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id));
+ if (pkt_type == MQTT_MSG_TYPE_SUBACK) {
+ if (length < 3) {
+ MQTT_DEBUGF(("mqtt_message_received: To small SUBACK packet\n"));
+ goto out_disconnect;
+ } else {
+ mqtt_incomming_suback(r, var_hdr_payload[2]);
+ }
+ } else if (r->cb != NULL) {
+ r->cb(r->arg, MQTT_ERR_OK);
+ }
+ mqtt_delete_request(r);
+ } else {
+ MQTT_DEBUGF(( "mqtt_message_received: Received %s reply, with wrong pkt_id: %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id));
+ }
+ } else {
+ MQTT_DEBUGF(( "mqtt_message_received: Received unknown message type: %d\n", pkt_type));
+ goto out_disconnect;
+ }
+ }
+ return res;
+out_disconnect:
+ return MQTT_CONNECT_DISCONNECTED;
+}
+
+
+/**
+ * MQTT incoming message parser
+ * @param client MQTT client
+ * @param p PBUF chain of received data
+ * @return Connection status
+ */
+mqtt_connection_status_t
+mqtt_parse_incoming(mqtt_client_t *client)
+{
+ uint16_t in_offset = 0, tot_len = 0;
+ uint32_t msg_rem_len = 0;
+ uint8_t fixed_hdr_idx = 0;
+ uint8_t b = 0;
+ mqtt_transport_intf_t *conn = client->conn;
+
+ MQTT_ASSERT("mqtt_parse_incoming(), conn != NULL", client->conn != NULL);
+ MQTT_ASSERT("mqtt_parse_incoming(), conn->recv_cb != NULL", conn->recv_from_network != NULL);
+ MQTT_ASSERT("mqtt_parse_incoming(), conn->recv_len_cb != NULL", conn->get_recv_len != NULL);
+ tot_len = conn->get_recv_len(conn->connCtxt);
+ while (tot_len > in_offset) {
+ /* We ALWAYS parse the header here first. Even if the header was not
+ included in this segment, we re-parse it here by buffering it in
+ client->rx_buffer. client->msg_idx keeps track of this. */
+ if ((fixed_hdr_idx < 2) || ((b & 0x80) != 0)) {
+
+ if (fixed_hdr_idx < client->msg_idx) {
+ /* parse header from old pbuf (buffered in client->rx_buffer) */
+ b = client->rx_buffer[fixed_hdr_idx];
+ } else {
+ /* parse header from this pbuf and save it in client->rx_buffer in case
+ it comes in segmented */
+ conn->recv_from_network(conn->connCtxt, &b, 1, in_offset++);
+ client->rx_buffer[client->msg_idx++] = b;
+ }
+ fixed_hdr_idx++;
+
+ if (fixed_hdr_idx >= 2) {
+ /* fixed header contains at least 2 bytes but can contain more, depending on
+ 'remaining length'. All bytes but the last of this have 0x80 set to
+ indicate more bytes are coming. */
+ msg_rem_len |= (uint32_t)(b & 0x7f) << ((fixed_hdr_idx - 2) * 7);
+ if ((b & 0x80) == 0) {
+ /* fixed header is done */
+ MQTT_DEBUGF(("mqtt_parse_incoming: Remaining length after fixed header: %u\n", msg_rem_len));
+ if (msg_rem_len == 0) {
+ /* Complete message with no extra headers of payload received */
+ mqtt_message_received(client, fixed_hdr_idx, 0, 0);
+ client->msg_idx = 0;
+ fixed_hdr_idx = 0;
+ } else {
+ /* Bytes remaining in message (changes remaining length if this is
+ not the first segment of this message) */
+ msg_rem_len = (msg_rem_len + fixed_hdr_idx) - client->msg_idx;
+ }
+ }
+ }
+ } else {
+ /* Fixed header has been parsed, parse variable header */
+ uint16_t cpy_len, cpy_start, buffer_space;
+
+ cpy_start = (client->msg_idx - fixed_hdr_idx) % (MQTT_VAR_HEADER_BUFFER_LEN - fixed_hdr_idx) + fixed_hdr_idx;
+
+ /* Allow to copy the lesser one of available length in input data or bytes remaining in message */
+ cpy_len = (uint16_t)MQTT_MIN((uint16_t)(tot_len - in_offset), msg_rem_len);
+
+ /* Limit to available space in buffer */
+ buffer_space = MQTT_VAR_HEADER_BUFFER_LEN - cpy_start;
+ if (cpy_len > buffer_space) {
+ cpy_len = buffer_space;
+ }
+ conn->recv_from_network(conn->connCtxt, client->rx_buffer + cpy_start, cpy_len, in_offset);
+
+ /* Advance get and put indexes */
+ client->msg_idx += cpy_len;
+ in_offset += cpy_len;
+ msg_rem_len -= cpy_len;
+
+ MQTT_DEBUGF(("mqtt_parse_incoming: msg_idx: %u, cpy_len: %u, remaining %u\n", client->msg_idx, cpy_len, msg_rem_len));
+ if ((msg_rem_len == 0) || (cpy_len == buffer_space)) {
+ /* Whole message received or buffer is full */
+ mqtt_connection_status_t res = mqtt_message_received(client, fixed_hdr_idx, (cpy_start + cpy_len) - fixed_hdr_idx, msg_rem_len);
+ if (res != MQTT_CONNECT_ACCEPTED) {
+ return res;
+ }
+ if (msg_rem_len == 0) {
+ /* Reset parser state */
+ client->msg_idx = 0;
+ /* msg_tot_len = 0; */
+ fixed_hdr_idx = 0;
+ }
+ }
+ }
+ }
+ return MQTT_CONNECT_ACCEPTED;
+}
+
+/*---------------------------------------------------------------------------------------------------- */
+/* Public API */
+
+
+/**
+ * @ingroup mqtt
+ * MQTT publish function.
+ * @param client MQTT client
+ * @param topic Publish topic string
+ * @param payload Data to publish (NULL is allowed)
+ * @param payload_length Length of payload (0 is allowed)
+ * @param qos Quality of service, 0 1 or 2
+ * @param retain MQTT retain flag
+ * @param cb Callback to call when publish is complete or has timed out
+ * @param arg User supplied argument to publish callback
+ * @return MQTT_ERR_OK if successful
+ * MQTT_ERR_CONN if client is disconnected
+ * MQTT_ERR_MEM if short on memory
+ */
+mqtt_err_t
+mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, uint16_t payload_length, uint8_t qos, uint8_t retain,
+ mqtt_request_cb_t cb, void *arg)
+{
+ struct mqtt_request_t *r;
+ uint16_t pkt_id;
+ size_t topic_strlen;
+ size_t total_len;
+ uint16_t topic_len;
+ uint16_t remaining_length;
+
+ MQTT_ASSERT_CORE_LOCKED();
+ MQTT_ASSERT("mqtt_publish: client != NULL", client);
+ MQTT_ASSERT("mqtt_publish: topic != NULL", topic);
+ MQTT_ERROR("mqtt_publish: TCP disconnected", (client->conn_state != TCP_DISCONNECTED), return MQTT_ERR_CONN);
+
+ topic_strlen = strlen(topic);
+ MQTT_ERROR("mqtt_publish: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return MQTT_ERR_ARG);
+ topic_len = (uint16_t)topic_strlen;
+ total_len = 2 + topic_len + payload_length;
+
+ if (qos > 0) {
+ total_len += 2;
+ /* Generate pkt_id id for QoS1 and 2 */
+ pkt_id = msg_generate_packet_id(client);
+ } else {
+ /* Use reserved value pkt_id 0 for QoS 0 in request handle */
+ pkt_id = 0;
+ }
+ MQTT_ERROR("mqtt_publish: total length overflow", (total_len <= 0xFFFF), return MQTT_ERR_ARG);
+ remaining_length = (uint16_t)total_len;
+
+ MQTT_DEBUGF(("mqtt_publish: Publish with payload length %d to topic \"%s\"\n", payload_length, topic));
+
+ r = mqtt_create_request(client->req_list, MQTT_ARRAYSIZE(client->req_list), pkt_id, cb, arg);
+ if (r == NULL) {
+ return MQTT_ERR_MEM;
+ }
+
+ if (mqtt_output_check_space(&client->output, remaining_length) == 0) {
+ mqtt_delete_request(r);
+ return MQTT_ERR_MEM;
+ }
+ /* Append fixed header */
+ mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain, remaining_length);
+
+ /* Append Topic */
+ mqtt_output_append_string(&client->output, topic, topic_len);
+
+ /* Append packet if for QoS 1 and 2*/
+ if (qos > 0) {
+ mqtt_output_append_uint16(&client->output, pkt_id);
+ }
+
+ /* Append optional publish payload */
+ if ((payload != NULL) && (payload_length > 0)) {
+ mqtt_output_append_buf(&client->output, payload, payload_length);
+ }
+
+ mqtt_append_request(&client->pend_req_queue, r);
+ mqtt_output_send(&client->output, client->conn);
+ return MQTT_ERR_OK;
+}
+
+
+/**
+ * @ingroup mqtt
+ * MQTT subscribe/unsubscribe function.
+ * @param client MQTT client
+ * @param topic topic to subscribe to
+ * @param qos Quality of service, 0 1 or 2 (only used for subscribe)
+ * @param cb Callback to call when subscribe/unsubscribe reponse is received
+ * @param arg User supplied argument to publish callback
+ * @param sub 1 for subscribe, 0 for unsubscribe
+ * @return MQTT_ERR_OK if successful, @see mqtt_err_t enum for other results
+ */
+mqtt_err_t
+mqtt_sub_unsub(mqtt_client_t *client, const char *topic, uint8_t qos, mqtt_request_cb_t cb, void *arg, uint8_t sub)
+{
+ size_t topic_strlen;
+ size_t total_len;
+ uint16_t topic_len;
+ uint16_t remaining_length;
+ uint16_t pkt_id;
+ struct mqtt_request_t *r;
+
+ MQTT_ASSERT_CORE_LOCKED();
+ MQTT_ASSERT("mqtt_sub_unsub: client != NULL", client);
+ MQTT_ASSERT("mqtt_sub_unsub: topic != NULL", topic);
+
+ topic_strlen = strlen(topic);
+ MQTT_ERROR("mqtt_sub_unsub: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return MQTT_ERR_ARG);
+ topic_len = (uint16_t)topic_strlen;
+ /* Topic string, pkt_id, qos for subscribe */
+ total_len = topic_len + 2 + 2 + (sub != 0);
+ MQTT_ERROR("mqtt_sub_unsub: total length overflow", (total_len <= 0xFFFF), return MQTT_ERR_ARG);
+ remaining_length = (uint16_t)total_len;
+
+ MQTT_ASSERT("mqtt_sub_unsub: qos < 3", qos < 3);
+ if (client->conn_state == TCP_DISCONNECTED) {
+ MQTT_DEBUGF( ("mqtt_sub_unsub: Can not (un)subscribe in disconnected state\n"));
+ return MQTT_ERR_CONN;
+ }
+
+ pkt_id = msg_generate_packet_id(client);
+ r = mqtt_create_request(client->req_list, MQTT_ARRAYSIZE(client->req_list), pkt_id, cb, arg);
+ if (r == NULL) {
+ return MQTT_ERR_MEM;
+ }
+
+ if (mqtt_output_check_space(&client->output, remaining_length) == 0) {
+ mqtt_delete_request(r);
+ return MQTT_ERR_MEM;
+ }
+
+ MQTT_DEBUGF(("mqtt_sub_unsub: Client (un)subscribe to topic \"%s\", id: %d\n", topic, pkt_id));
+
+ mqtt_output_append_fixed_header(&client->output, sub ? MQTT_MSG_TYPE_SUBSCRIBE : MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0, remaining_length);
+ /* Packet id */
+ mqtt_output_append_uint16(&client->output, pkt_id);
+ /* Topic */
+ mqtt_output_append_string(&client->output, topic, topic_len);
+ /* QoS */
+ if (sub != 0) {
+ mqtt_output_append_uint8(&client->output, MQTT_MIN(qos, 2));
+ }
+
+ mqtt_append_request(&client->pend_req_queue, r);
+ mqtt_output_send(&client->output, client->conn);
+ return MQTT_ERR_OK;
+}
+
+
+/**
+ * @ingroup mqtt
+ * Set callback to handle incoming publish requests from server
+ * @param client MQTT client
+ * @param pub_cb Callback invoked when publish starts, contain topic and total length of payload
+ * @param data_cb Callback for each fragment of payload that arrives
+ * @param arg User supplied argument to both callbacks
+ */
+void
+mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t pub_cb,
+ mqtt_incoming_data_cb_t data_cb, void *arg)
+{
+ MQTT_ASSERT_CORE_LOCKED();
+ MQTT_ASSERT("mqtt_set_inpub_callback: client != NULL", client != NULL);
+ client->data_cb = data_cb;
+ client->pub_cb = pub_cb;
+ client->inpub_arg = arg;
+}
+
+/**
+ * @ingroup mqtt
+ * Create a new MQTT client instance
+ * @return Pointer to instance on success, NULL otherwise
+ */
+mqtt_client_t *
+mqtt_client_new(void)
+{
+ MQTT_ASSERT_CORE_LOCKED();
+ return (mqtt_client_t *)mem_calloc(1, sizeof(mqtt_client_t));
+}
+
+/**
+ * @ingroup mqtt
+ * Free MQTT client instance
+ * @param client Pointer to instance to be freed
+ */
+void
+mqtt_client_free(mqtt_client_t *client)
+{
+ mem_free(client);
+}
+
+/**
+ * @ingroup mqtt
+ * Connect to MQTT server
+ * @param client MQTT client
+ * @param ip_addr Server IP
+ * @param port Server port
+ * @param cb Connection state change callback
+ * @param arg User supplied argument to connection callback
+ * @param client_info Client identification and connection options
+ * @return MQTT_ERR_OK if successful, @see mqtt_err_t enum for other results
+ */
+mqtt_err_t
+mqtt_client_connect(mqtt_client_t *client, void *conn, mqtt_connection_cb_t cb, void *arg,
+ const struct mqtt_connect_client_info_t *client_info)
+{
+ size_t len;
+ uint16_t client_id_length;
+ /* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */
+ uint16_t remaining_length = 2 + 4 + 1 + 1 + 2;
+ uint8_t flags = 0, will_topic_len = 0, will_msg_len = 0;
+ uint16_t client_user_len = 0, client_pass_len = 0;
+
+ MQTT_ASSERT_CORE_LOCKED();
+ MQTT_ASSERT("mqtt_client_connect: client != NULL", client != NULL);
+ MQTT_ASSERT("mqtt_client_connect: conn != NULL", conn != NULL);
+ MQTT_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL);
+ MQTT_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL);
+
+ if (client->conn_state != TCP_DISCONNECTED) {
+ MQTT_DEBUGF(("mqtt_client_connect: Already connected\n"));
+ return MQTT_ERR_ISCONN;
+ }
+
+ /* Wipe clean */
+ memset(client, 0, sizeof(mqtt_client_t));
+ client->connect_arg = arg;
+ client->connect_cb = cb;
+ client->keep_alive = client_info->keep_alive;
+ mqtt_init_requests(client->req_list, MQTT_ARRAYSIZE(client->req_list));
+
+ /* Build connect message */
+ if (client_info->will_topic != NULL && client_info->will_msg != NULL) {
+ flags |= MQTT_CONNECT_FLAG_WILL;
+ flags |= (client_info->will_qos & 3) << 3;
+ if (client_info->will_retain) {
+ flags |= MQTT_CONNECT_FLAG_WILL_RETAIN;
+ }
+ len = strlen(client_info->will_topic);
+ MQTT_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return MQTT_ERR_VAL);
+ MQTT_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return MQTT_ERR_VAL);
+ will_topic_len = (uint8_t)len;
+ len = strlen(client_info->will_msg);
+ MQTT_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return MQTT_ERR_VAL);
+ will_msg_len = (uint8_t)len;
+ len = remaining_length + 2 + will_topic_len + 2 + will_msg_len;
+ MQTT_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return MQTT_ERR_VAL);
+ remaining_length = (uint16_t)len;
+ }
+ if (client_info->client_user != NULL) {
+ flags |= MQTT_CONNECT_FLAG_USERNAME;
+ len = strlen(client_info->client_user);
+ MQTT_ERROR("mqtt_client_connect: client_info->client_user length overflow", len <= 0xFFFF, return MQTT_ERR_VAL);
+ MQTT_ERROR("mqtt_client_connect: client_info->client_user length must be > 0", len > 0, return MQTT_ERR_VAL);
+ client_user_len = (uint16_t)len;
+ len = remaining_length + 2 + client_user_len;
+ MQTT_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return MQTT_ERR_VAL);
+ remaining_length = (uint16_t)len;
+ }
+ if (client_info->client_pass != NULL) {
+ flags |= MQTT_CONNECT_FLAG_PASSWORD;
+ len = strlen(client_info->client_pass);
+ MQTT_ERROR("mqtt_client_connect: client_info->client_pass length overflow", len <= 0xFFFF, return MQTT_ERR_VAL);
+ MQTT_ERROR("mqtt_client_connect: client_info->client_pass length must be > 0", len > 0, return MQTT_ERR_VAL);
+ client_pass_len = (uint16_t)len;
+ len = remaining_length + 2 + client_pass_len;
+ MQTT_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return MQTT_ERR_VAL);
+ remaining_length = (uint16_t)len;
+ }
+
+ /* Don't complicate things, always connect using clean session */
+ flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
+
+ len = strlen(client_info->client_id);
+ MQTT_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return MQTT_ERR_VAL);
+ client_id_length = (uint16_t)len;
+ len = remaining_length + 2 + client_id_length;
+ MQTT_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return MQTT_ERR_VAL);
+ remaining_length = (uint16_t)len;
+
+ if (mqtt_output_check_space(&client->output, remaining_length) == 0) {
+ return MQTT_ERR_MEM;
+ }
+
+ /* Append fixed header */
+ mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length);
+ /* Append Protocol string */
+ mqtt_output_append_string(&client->output, "MQTT", 4);
+ /* Append Protocol level */
+ mqtt_output_append_uint8(&client->output, 4);
+ /* Append connect flags */
+ mqtt_output_append_uint8(&client->output, flags);
+ /* Append keep-alive */
+ mqtt_output_append_uint16(&client->output, client_info->keep_alive);
+ /* Append client id */
+ mqtt_output_append_string(&client->output, client_info->client_id, client_id_length);
+ /* Append will message if used */
+ if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) {
+ mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len);
+ mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len);
+ }
+ /* Append user name if given */
+ if ((flags & MQTT_CONNECT_FLAG_USERNAME) != 0) {
+ mqtt_output_append_string(&client->output, client_info->client_user, client_user_len);
+ }
+ /* Append password if given */
+ if ((flags & MQTT_CONNECT_FLAG_PASSWORD) != 0) {
+ mqtt_output_append_string(&client->output, client_info->client_pass, client_pass_len);
+ }
+ client->conn = conn;
+
+ /* Initiate receiver state */
+ client->msg_idx = 0;
+ /* Enter MQTT connect state */
+ client->conn_state = MQTT_CONNECTING;
+
+ /* Start cyclic timer */
+ client->conn->timer_start(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, client);
+ client->cyclic_tick = 0;
+
+ /* Start transmission from output queue, connect message is the first one out*/
+ mqtt_output_send(&client->output, client->conn);
+
+ return MQTT_ERR_OK;
+}
+
+
+/**
+ * @ingroup mqtt
+ * Disconnect from MQTT server
+ * @param client MQTT client
+ */
+void
+mqtt_disconnect(mqtt_client_t *client)
+{
+ MQTT_ASSERT_CORE_LOCKED();
+ MQTT_ASSERT("mqtt_disconnect: client != NULL", client);
+ /* If connection in not already closed */
+ if (client->conn_state != TCP_DISCONNECTED) {
+ /* Set conn_state before calling mqtt_close to prevent callback from being called */
+ client->conn_state = TCP_DISCONNECTED;
+ mqtt_close(client, (mqtt_connection_status_t)0);
+ }
+}
+
+/**
+ * @ingroup mqtt
+ * Check connection with server
+ * @param client MQTT client
+ * @return 1 if connected to server, 0 otherwise
+ */
+uint8_t
+mqtt_client_is_connected(mqtt_client_t *client)
+{
+ MQTT_ASSERT_CORE_LOCKED();
+ MQTT_ASSERT("mqtt_client_is_connected: client != NULL", client);
+ return client->conn_state == MQTT_CONNECTED;
+}
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/stack/mqtt.h b/third_party/silabs/mqtt/stack/mqtt.h
new file mode 100644
index 00000000000000..c273615e22823d
--- /dev/null
+++ b/third_party/silabs/mqtt/stack/mqtt.h
@@ -0,0 +1,350 @@
+/**
+ * @file
+ * MQTT client
+ */
+
+/*
+ * Copyright (c) 2016 Erik Andersson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Erik Andersson
+ *
+ */
+#ifndef MQTT_H
+#define MQTT_H
+
+#include "mqtt_opts.h"
+#include
+#include
+#include
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef uint8_t mqtt_err_t;
+typedef uint32_t mqtt_mem_size_t;
+
+typedef struct mqtt_client_t mqtt_client_t;
+typedef struct mqtt_transport_intf_t mqtt_transport_intf_t;
+
+#define MQTT_MIN(x , y) (((x) < (y)) ? (x) : (y))
+#define MQTT_ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))
+
+#ifdef ERR_FAIL
+#undef ERR_FAIL
+#endif
+#define ERR_FAIL -1
+
+#define MQTT_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
+ x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
+
+#define MQTT_PLATFORM_ERROR(message) MQTT_PLATFORM_ASSERT(message)
+
+/* if "expression" isn't true, then print "message" and execute "handler" expression */
+#define MQTT_ERROR(message, expression, handler) do { if (!(expression)) { \
+ MQTT_PLATFORM_ERROR(message); handler;}} while(0)
+
+#define MQTT_ASSERT(message, assertion) do { if (!(assertion)) { \
+ MQTT_PLATFORM_ASSERT(message); }} while(0)
+
+/* Flags for "apiflags" parameter in tcp_write */
+#define MQTT_WRITE_FLAG_COPY 0x01
+#define MQTT_WRITE_FLAG_MORE 0x02
+
+/*--------------------------------------------------------------------------------------------------------------------- */
+/* Output ring buffer */
+
+#define MQTT_RINGBUF_IDX_MASK ((MQTT_OUTPUT_RINGBUF_SIZE) - 1)
+
+/** Add single item to ring buffer */
+#define mqtt_ringbuf_put(rb, item) ((rb)->buf)[(rb)->put++ & MQTT_RINGBUF_IDX_MASK] = (item)
+
+/** Return number of bytes in ring buffer */
+#define mqtt_ringbuf_len(rb) ((uint16_t)((rb)->put - (rb)->get))
+
+/** Return number of bytes free in ring buffer */
+#define mqtt_ringbuf_free(rb) (MQTT_OUTPUT_RINGBUF_SIZE - mqtt_ringbuf_len(rb))
+
+/** Return number of bytes possible to read without wrapping around */
+#define mqtt_ringbuf_linear_read_length(rb) MQTT_MIN(mqtt_ringbuf_len(rb), (MQTT_OUTPUT_RINGBUF_SIZE - ((rb)->get & MQTT_RINGBUF_IDX_MASK)))
+
+/** Return pointer to ring buffer get position */
+#define mqtt_ringbuf_get_ptr(rb) (&(rb)->buf[(rb)->get & MQTT_RINGBUF_IDX_MASK])
+
+#define mqtt_ringbuf_advance_get_idx(rb, len) ((rb)->get += (len))
+
+
+/**
+ * MQTT client connection states
+ */
+enum {
+ TCP_DISCONNECTED,
+ TCP_CONNECTING,
+ MQTT_CONNECTING,
+ MQTT_CONNECTED
+};
+
+enum {
+ /** No error, everything OK. */
+ MQTT_ERR_OK = 0,
+ /** Out of memory error. */
+ MQTT_ERR_MEM = -1,
+ /** Timeout. */
+ MQTT_ERR_TIMEOUT = -3,
+ /** Illegal value. */
+ MQTT_ERR_VAL = -6,
+ /** Conn already established.*/
+ MQTT_ERR_ISCONN = -10,
+ /** Not connected. */
+ MQTT_ERR_CONN = -11,
+ /** Connection aborted. */
+ MQTT_ERR_ABRT = -13,
+ /** Illegal argument. */
+ MQTT_ERR_ARG = -16,
+
+};
+/** @ingroup mqtt
+ * Default MQTT port */
+#define MQTT_PORT 1883
+
+/*---------------------------------------------------------------------------------------------- */
+/* Connection with server */
+
+/**
+ * @ingroup mqtt
+ * Client information and connection parameters */
+struct mqtt_connect_client_info_t {
+ /** Client identifier, must be set by caller */
+ const char *client_id;
+ /** User name and password, set to NULL if not used */
+ const char* client_user;
+ const char* client_pass;
+ /** keep alive time in seconds, 0 to disable keep alive functionality*/
+ uint16_t keep_alive;
+ /** will topic, set to NULL if will is not to be used,
+ will_msg, will_qos and will retain are then ignored */
+ const char* will_topic;
+ const char* will_msg;
+ uint8_t will_qos;
+ uint8_t will_retain;
+};
+
+/**
+ * @ingroup mqtt
+ * Connection status codes */
+typedef enum
+{
+ MQTT_CONNECT_ACCEPTED = 0,
+ MQTT_CONNECT_REFUSED_PROTOCOL_VERSION = 1,
+ MQTT_CONNECT_REFUSED_IDENTIFIER = 2,
+ MQTT_CONNECT_REFUSED_SERVER = 3,
+ MQTT_CONNECT_REFUSED_USERNAME_PASS = 4,
+ MQTT_CONNECT_REFUSED_NOT_AUTHORIZED_ = 5,
+ MQTT_CONNECT_DISCONNECTED = 256,
+ MQTT_CONNECT_TIMEOUT = 257
+} mqtt_connection_status_t;
+
+/**
+ * @ingroup mqtt
+ * Function prototype for mqtt connection status callback. Called when
+ * client has connected to the server after initiating a mqtt connection attempt by
+ * calling mqtt_connect() or when connection is closed by server or an error
+ *
+ * @param client MQTT client itself
+ * @param arg Additional argument to pass to the callback function
+ * @param status Connect result code or disconnection notification @see mqtt_connection_status_t
+ *
+ */
+typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status);
+
+
+/**
+ * @ingroup mqtt
+ * Data callback flags */
+enum {
+ /** Flag set when last fragment of data arrives in data callback */
+ MQTT_DATA_FLAG_LAST = 1
+};
+
+/**
+ * @ingroup mqtt
+ * Function prototype for MQTT incoming publish data callback function. Called when data
+ * arrives to a subscribed topic @see mqtt_subscribe
+ *
+ * @param arg Additional argument to pass to the callback function
+ * @param data User data, pointed object, data may not be referenced after callback return,
+ NULL is passed when all publish data are delivered
+ * @param len Length of publish data fragment
+ * @param flags MQTT_DATA_FLAG_LAST set when this call contains the last part of data from publish message
+ *
+ */
+typedef void (*mqtt_incoming_data_cb_t)(void *arg, const uint8_t *data, uint16_t len, uint8_t flags);
+
+
+/**
+ * @ingroup mqtt
+ * Function prototype for MQTT incoming publish function. Called when an incoming publish
+ * arrives to a subscribed topic @see mqtt_subscribe
+ *
+ * @param arg Additional argument to pass to the callback function
+ * @param topic Zero terminated Topic text string, topic may not be referenced after callback return
+ * @param tot_len Total length of publish data, if set to 0 (no publish payload) data callback will not be invoked
+ */
+typedef void (*mqtt_incoming_publish_cb_t)(void *arg, const char *topic, uint32_t tot_len);
+
+
+/**
+ * @ingroup mqtt
+ * Function prototype for mqtt request callback. Called when a subscribe, unsubscribe
+ * or publish request has completed
+ * @param arg Pointer to user data supplied when invoking request
+ * @param err ERR_OK on success
+ * ERR_TIMEOUT if no response was received within timeout,
+ * ERR_ABRT if (un)subscribe was denied
+ */
+typedef void (*mqtt_request_cb_t)(void *arg, mqtt_err_t err);
+
+
+/**
+ * Pending request item, binds application callback to pending server requests
+ */
+struct mqtt_request_t
+{
+ /** Next item in list, NULL means this is the last in chain,
+ next pointing at itself means request is unallocated */
+ struct mqtt_request_t *next;
+ /** Callback to upper layer */
+ mqtt_request_cb_t cb;
+ void *arg;
+ /** MQTT packet identifier */
+ uint16_t pkt_id;
+ /** Expire time relative to element before this */
+ uint16_t timeout_diff;
+};
+
+/** Ring buffer */
+struct mqtt_ringbuf_t {
+ uint16_t put;
+ uint16_t get;
+ uint8_t buf[MQTT_OUTPUT_RINGBUF_SIZE];
+};
+
+typedef uint16_t (*mqtt_ti_getsndLen)(void *conn);
+typedef int8_t (*mqtt_send_to_network)(void *conn, void *buff, uint16_t len, uint8_t flags, uint8_t isFinal);
+typedef uint16_t (*mqtt_ti_getrcvLen)(void *conn);
+typedef int8_t (*mqtt_recv_from_network)(void *conn, void * buf, uint16_t len, uint16_t offset);
+typedef void (*mqtt_close_connection)(void *conn);
+
+typedef void (*timer_callback)(void *arg);
+typedef void (*mqtt_timer_start)(uint32_t msecs, timer_callback handler, void *arg);
+typedef void (*mqtt_timer_stop)(timer_callback handler, void *arg);
+
+struct mqtt_transport_intf_t {
+ void *connCtxt;
+ mqtt_send_to_network send_to_network;
+ mqtt_ti_getsndLen get_send_len;
+ mqtt_recv_from_network recv_from_network;
+ mqtt_ti_getrcvLen get_recv_len;
+ mqtt_close_connection close_connection;
+ mqtt_timer_start timer_start;
+ mqtt_timer_stop timer_stop;
+ void *app_recv;
+};
+
+/** MQTT client */
+struct mqtt_client_t
+{
+ /** Timers and timeouts */
+ uint16_t cyclic_tick;
+ uint16_t keep_alive;
+ uint16_t server_watchdog;
+ /** Packet identifier generator*/
+ uint16_t pkt_id_seq;
+ /** Packet identifier of pending incoming publish */
+ uint16_t inpub_pkt_id;
+ /** Connection state */
+ uint8_t conn_state;
+ mqtt_transport_intf_t *conn;
+ /** Connection callback */
+ void *connect_arg;
+ mqtt_connection_cb_t connect_cb;
+ /** Pending requests to server */
+ struct mqtt_request_t *pend_req_queue;
+ struct mqtt_request_t req_list[MQTT_REQ_MAX_IN_FLIGHT];
+ void *inpub_arg;
+ /** Incoming data callback */
+ mqtt_incoming_data_cb_t data_cb;
+ mqtt_incoming_publish_cb_t pub_cb;
+ /** Input */
+ uint32_t msg_idx;
+ uint8_t rx_buffer[MQTT_VAR_HEADER_BUFFER_LEN];
+ /** Output ring-buffer */
+ struct mqtt_ringbuf_t output;
+};
+
+
+/** Connect to server */
+mqtt_err_t mqtt_client_connect(mqtt_client_t *client, void *conn, mqtt_connection_cb_t cb, void *arg,
+ const struct mqtt_connect_client_info_t *client_info);
+
+/** Disconnect from server */
+void mqtt_disconnect(mqtt_client_t *client);
+
+/** Create new client */
+mqtt_client_t *mqtt_client_new(void);
+
+/** Check connection status */
+uint8_t mqtt_client_is_connected(mqtt_client_t *client);
+
+/** Set callback to call for incoming publish */
+void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t,
+ mqtt_incoming_data_cb_t data_cb, void *arg);
+
+/** Common function for subscribe and unsubscribe */
+mqtt_err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, uint8_t qos, mqtt_request_cb_t cb, void *arg, uint8_t sub);
+
+/** @ingroup mqtt
+ *Subscribe to topic */
+#define mqtt_subscribe(client, topic, qos, cb, arg) mqtt_sub_unsub(client, topic, qos, cb, arg, 1)
+/** @ingroup mqtt
+ * Unsubscribe to topic */
+#define mqtt_unsubscribe(client, topic, cb, arg) mqtt_sub_unsub(client, topic, 0, cb, arg, 0)
+
+
+/** Publish data to topic */
+mqtt_err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, uint16_t payload_length, uint8_t qos, uint8_t retain,
+ mqtt_request_cb_t cb, void *arg);
+
+void *mqtt_mem_calloc(mqtt_mem_size_t count, mqtt_mem_size_t size);
+void mqtt_close(mqtt_client_t *client, mqtt_connection_status_t reason);
+
+void mqtt_process(mqtt_client_t *client, uint8_t isTx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MQTT_H */
\ No newline at end of file
diff --git a/third_party/silabs/mqtt/stack/mqtt_opts.h b/third_party/silabs/mqtt/stack/mqtt_opts.h
new file mode 100644
index 00000000000000..5bd02d9e7cf2d1
--- /dev/null
+++ b/third_party/silabs/mqtt/stack/mqtt_opts.h
@@ -0,0 +1,96 @@
+/**
+ * @file
+ * MQTT client options
+ */
+
+/*
+ * Copyright (c) 2016 Erik Andersson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Erik Andersson
+ *
+ */
+#ifndef MQTT_OPTS_H
+#define MQTT_OPTS_H
+
+//#include "lwip/opt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup mqtt_opts Options
+ * @ingroup mqtt
+ * @{
+ */
+#define MQTT_DEBUG 0x0
+/**
+ * Output ring-buffer size, must be able to fit largest outgoing publish message topic+payloads
+ */
+#define MQTT_OUTPUT_RINGBUF_SIZE 256
+
+/**
+ * Number of bytes in receive buffer, must be at least the size of the longest incoming topic + 8
+ * If one wants to avoid fragmented incoming publish, set length to max incoming topic length + max payload length + 8
+ */
+
+#define MQTT_VAR_HEADER_BUFFER_LEN 128
+
+/**
+ * Maximum number of pending subscribe, unsubscribe and publish requests to server .
+ */
+
+#define MQTT_REQ_MAX_IN_FLIGHT 4
+
+/**
+ * Seconds between each cyclic timer call.
+ */
+
+#define MQTT_CYCLIC_TIMER_INTERVAL 5
+
+/**
+ * Publish, subscribe and unsubscribe request timeout in seconds.
+ */
+
+#define MQTT_REQ_TIMEOUT 30
+
+/**
+ * Seconds for MQTT connect response timeout after sending connect request
+ */
+
+#define MQTT_CONNECT_TIMOUT 100
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LWIP_HDR_APPS_MQTT_OPTS_H */
\ No newline at end of file