Skip to content

Commit 7cf82dc

Browse files
[SL-ONLY] MATTER-7023: Changes as per feedback on Alpha1 (#1165)
* Added conditional compilation for HTTP client feature under dual-stack settings and improved formatting for clarity. * Update response handling to utilize mEndOfData for improved clarity in data state management. * Refactor MQTT client header and implementation to improve clarity by moving the MQTT_USE_HOST_LWIP_TLS definition to the header file and removing it from the source file. This change enhances code organization and maintains consistent configuration management. * Enhance documentation in matter_service.h to clarify the purpose of the initialization delay for Matter services, ensuring the network is fully established before service startup. * Updating MQTT HEAP to 60K as per expectation * Refactor HTTPS client configuration to use default certificate index for improved clarity and maintainability. Removed hardcoded certificate index in the demo example. * Revert the RAM changes * Move to AppTask instead of BaseApplicationTask * Enhance MQTT client functionality by adding idle yield management and subscription callback for incoming messages. Updated the MQTT service thread to handle idle conditions more effectively, ensuring timely keepalive and message processing. Improved logging for MQTT operations to provide clearer feedback on session status. * Replaced direct disconnection flag manipulation with a dedicated ProcessDisconnect function for better clarity and maintainability. * Enhance MQTT client by adding comments to clarify idle yield timeout logic and its default value. Ensure that idle yield timeout does not exceed the keep-alive interval, improving connection stability and maintainability. * Adding a TODO comment to revisit idle yield timeout calculations. This aims to streamline the connection keep-alive process by suggesting a more efficient invocation of the MQTTYield function. * Improve error handling in MQTT disconnection process by logging failures in ProcessDisconnect during idle yield and yield operations. This enhances debugging capabilities and ensures better visibility of connection issues. * [PATCH] Restyled by whitespace
1 parent 44324be commit 7cf82dc

10 files changed

Lines changed: 158 additions & 64 deletions

File tree

‎examples/platform/silabs/BaseApplication.cpp‎

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -89,20 +89,6 @@
8989
#include "MatterAwsControl.h"
9090
#endif // SL_MATTER_ENABLE_AWS
9191

92-
#if defined(SL_MATTER_ENABLE_SERVICES) && SL_MATTER_ENABLE_SERVICES
93-
94-
#include <platform/silabs/services/matter_service.h>
95-
96-
#if defined(SL_MATTER_ENABLE_HTTP_SERVICE) && SL_MATTER_ENABLE_HTTP_SERVICE
97-
#include "https_offload_example.h"
98-
#endif // SL_MATTER_ENABLE_HTTP_SERVICE
99-
100-
#if defined(SL_MATTER_ENABLE_MQTT_SERVICE) && SL_MATTER_ENABLE_MQTT_SERVICE
101-
#include "mqtt_example.h"
102-
#endif // SL_MATTER_ENABLE_MQTT_SERVICE
103-
104-
#endif // SL_MATTER_ENABLE_SERVICES
105-
10692
#ifdef PERFORMANCE_TEST_ENABLED
10793
#include <performance_test_commands.h>
10894
#endif // PERFORMANCE_TEST_ENABLED
@@ -1030,22 +1016,6 @@ void InitMatterAwsHandler(System::Layer * systemLayer, void * appState)
10301016
} // namespace
10311017
#endif // SL_MATTER_ENABLE_AWS
10321018

1033-
#if defined(SL_MATTER_ENABLE_SERVICES) && SL_MATTER_ENABLE_SERVICES
1034-
namespace {
1035-
void InitMatterServicesHandler(System::Layer * systemLayer, void * appState)
1036-
{
1037-
1038-
#if defined(SL_MATTER_ENABLE_MQTT_SERVICE) && SL_MATTER_ENABLE_MQTT_SERVICE
1039-
VerifyOrReturn(SL_STATUS_OK == mqtt_client_demo_start(), ChipLogError(AppServer, "mqtt_client_demo_start failed"));
1040-
#endif // SL_MATTER_ENABLE_MQTT_SERVICE
1041-
1042-
#if defined(SL_MATTER_ENABLE_HTTP_SERVICE) && SL_MATTER_ENABLE_HTTP_SERVICE
1043-
VerifyOrReturn(SL_STATUS_OK == https_client_demo_start(), ChipLogError(AppServer, "https_client_demo_start failed"));
1044-
#endif // SL_MATTER_ENABLE_HTTP_SERVICE
1045-
}
1046-
} // namespace
1047-
#endif // SL_MATTER_ENABLE_SERVICES
1048-
10491019
void BaseApplication::OnPlatformEvent(const ChipDeviceEvent * event, intptr_t)
10501020
{
10511021
switch (event->Type)
@@ -1071,19 +1041,6 @@ void BaseApplication::OnPlatformEvent(const ChipDeviceEvent * event, intptr_t)
10711041
}
10721042
#endif // SL_MATTER_ENABLE_AWS
10731043

1074-
#if defined(SL_MATTER_ENABLE_SERVICES) && SL_MATTER_ENABLE_SERVICES
1075-
if (event->InternetConnectivityChange.IPv4 == kConnectivity_Established
1076-
#if defined(SL_MATTER_ENABLE_DUAL_STACK) && SL_MATTER_ENABLE_DUAL_STACK
1077-
|| event->InternetConnectivityChange.IPv6 == kConnectivity_Established
1078-
#endif // SL_MATTER_ENABLE_DUAL_STACK
1079-
)
1080-
{
1081-
ChipLogProgress(AppServer, "Scheduling Matter Services initialization");
1082-
TEMPORARY_RETURN_IGNORED chip::DeviceLayer::SystemLayer().StartTimer(
1083-
chip::System::Clock::Seconds32(kMatterServicesInitDelaySec), InitMatterServicesHandler, nullptr);
1084-
}
1085-
#endif // SL_MATTER_ENABLE_SERVICES
1086-
10871044
#if SL_MATTER_DISPLAY_ENABLED
10881045
SilabsLCD::Screen_e screen;
10891046
AppTask::GetLCD().GetScreen(screen);

‎examples/thermostat/silabs/include/AppTask.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,9 @@ class AppTask : public BaseApplication
111111
* could not be created, or an error propagated from InitSensor().
112112
*/
113113
CHIP_ERROR InitThermostat();
114+
115+
#if defined(SL_MATTER_ENABLE_SERVICES) && SL_MATTER_ENABLE_SERVICES
116+
/** Schedule MQTT/HTTP service demos after internet connectivity is established. */
117+
static void MatterServicesEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
118+
#endif // SL_MATTER_ENABLE_SERVICES
114119
};

‎examples/thermostat/silabs/src/AppTask.cpp‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <platform/CHIPDeviceLayer.h>
4444
#include <platform/PlatformError.h>
4545
#include <platform/silabs/platformAbstraction/SilabsPlatform.h>
46+
#include <sl_cmsis_os2_common.h>
4647
#include <thermostat-delegate-impl.h>
4748

4849
#if defined(SL_MATTER_USE_SI70XX_SENSOR) && SL_MATTER_USE_SI70XX_SENSOR
@@ -53,6 +54,18 @@
5354
#include "MatterAwsControl.h"
5455
#endif // SL_MATTER_ENABLE_AWS
5556

57+
#if defined(SL_MATTER_ENABLE_SERVICES) && SL_MATTER_ENABLE_SERVICES
58+
#include <platform/silabs/services/matter_service.h>
59+
60+
#if defined(SL_MATTER_ENABLE_HTTP_SERVICE) && SL_MATTER_ENABLE_HTTP_SERVICE
61+
#include "https_offload_example.h"
62+
#endif // SL_MATTER_ENABLE_HTTP_SERVICE
63+
64+
#if defined(SL_MATTER_ENABLE_MQTT_SERVICE) && SL_MATTER_ENABLE_MQTT_SERVICE
65+
#include "mqtt_example.h"
66+
#endif // SL_MATTER_ENABLE_MQTT_SERVICE
67+
#endif // SL_MATTER_ENABLE_SERVICES
68+
5669
#define APP_FUNCTION_BUTTON 0
5770

5871
using namespace chip;
@@ -111,6 +124,15 @@ CHIP_ERROR AppTask::AppInit()
111124
appError(err);
112125
}
113126

127+
#if defined(SL_MATTER_ENABLE_SERVICES) && SL_MATTER_ENABLE_SERVICES
128+
err = PlatformMgr().AddEventHandler(MatterServicesEventHandler, 0);
129+
if (err != CHIP_NO_ERROR)
130+
{
131+
ChipLogError(AppServer, "MatterServicesEventHandler register failed: %" CHIP_ERROR_FORMAT, err.Format());
132+
appError(err);
133+
}
134+
#endif // SL_MATTER_ENABLE_SERVICES
135+
114136
return err;
115137
}
116138

@@ -360,6 +382,48 @@ void AppTask::DMThermostatClusterInit(chip::EndpointId endpoint)
360382
SetDefaultDelegate(endpoint, &delegate);
361383
}
362384

385+
#if defined(SL_MATTER_ENABLE_SERVICES) && SL_MATTER_ENABLE_SERVICES
386+
namespace {
387+
388+
using chip::DeviceLayer::Silabs::kMatterServicesInitDelaySec;
389+
390+
void InitMatterServicesHandler(System::Layer * /* systemLayer */, void * /* appState */)
391+
{
392+
#if defined(SL_MATTER_ENABLE_MQTT_SERVICE) && SL_MATTER_ENABLE_MQTT_SERVICE
393+
VerifyOrReturn(SL_STATUS_OK == mqtt_client_demo_start(), ChipLogError(AppServer, "mqtt_client_demo_start failed"));
394+
#endif // SL_MATTER_ENABLE_MQTT_SERVICE
395+
396+
#if defined(SL_MATTER_ENABLE_HTTP_SERVICE) && SL_MATTER_ENABLE_HTTP_SERVICE
397+
VerifyOrReturn(SL_STATUS_OK == https_client_demo_start(), ChipLogError(AppServer, "https_client_demo_start failed"));
398+
#endif // SL_MATTER_ENABLE_HTTP_SERVICE
399+
}
400+
401+
} // namespace
402+
403+
void AppTask::MatterServicesEventHandler(const ChipDeviceEvent * event, intptr_t)
404+
{
405+
VerifyOrReturn(event != nullptr);
406+
407+
if (event->Type != DeviceEventType::kInternetConnectivityChange)
408+
{
409+
return;
410+
}
411+
412+
if (event->InternetConnectivityChange.IPv4 != kConnectivity_Established
413+
#if defined(SL_MATTER_ENABLE_DUAL_STACK) && SL_MATTER_ENABLE_DUAL_STACK
414+
&& event->InternetConnectivityChange.IPv6 != kConnectivity_Established
415+
#endif // SL_MATTER_ENABLE_DUAL_STACK
416+
)
417+
{
418+
return;
419+
}
420+
421+
ChipLogProgress(AppServer, "Scheduling Matter Services initialization");
422+
TEMPORARY_RETURN_IGNORED SystemLayer().StartTimer(System::Clock::Seconds32(kMatterServicesInitDelaySec),
423+
InitMatterServicesHandler, nullptr);
424+
}
425+
#endif // SL_MATTER_ENABLE_SERVICES
426+
363427
// emberAfThermostatClusterInitCallback — weak ZAP entry point. CRTP forwarder into AppTask.
364428
void emberAfThermostatClusterInitCallback(chip::EndpointId endpoint)
365429
{

‎examples/thermostat/silabs/src/https_offload_example.cpp‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ sl_status_t https_client_demo_start(void)
167167
VerifyOrReturnError(sizeof(kCaCertExample) > 0, SL_STATUS_FAIL, ChipLogError(DeviceLayer, "CA certificate is not set"));
168168

169169
const HttpClientConfig config = {
170-
.certificateIndex = 1,
171170
// Enable HTTPS client.
172171
.httpsEnable = true,
173172
.username = kHttpClientUser,

‎examples/thermostat/silabs/src/mqtt_example.cpp‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,13 @@ void OnOperationDone(CHIP_ERROR result, void * /* context */)
5757
gOpDone = true;
5858
}
5959

60-
// Must yield: demo runs on the CHIP task (osPriorityHigh), which is above the
61-
// mqtt_client service thread (osPriorityAboveNormal). A tight spin deadlocks.
60+
void OnMqttMessage(const char * topic, ByteSpan payload, void * /* context */)
61+
{
62+
ChipLogProgress(DeviceLayer, "MQTT demo message on %s: %.*s", topic != nullptr ? topic : "(null)",
63+
static_cast<int>(payload.size()), reinterpret_cast<const char *>(payload.data()));
64+
}
65+
66+
// Must yield: demo may run above mqtt_client priority; osDelay lets the service thread run.
6267
CHIP_ERROR RunOperation(CHIP_ERROR queueResult)
6368
{
6469
if (queueResult != CHIP_NO_ERROR)
@@ -111,6 +116,8 @@ sl_status_t mqtt_client_demo_start(void)
111116
return SL_STATUS_FAIL;
112117
}
113118

119+
gMqttsClient.SetSubscriptionCallback(OnMqttMessage, nullptr);
120+
114121
ChipLogProgress(DeviceLayer, "MQTT demo starting");
115122

116123
gOpDone = false;
@@ -146,6 +153,6 @@ sl_status_t mqtt_client_demo_start(void)
146153
return SL_STATUS_FAIL;
147154
}
148155

149-
ChipLogProgress(DeviceLayer, "MQTT demo completed");
156+
ChipLogProgress(DeviceLayer, "MQTT demo completed (auto-yield keeps session alive)");
150157
return SL_STATUS_OK;
151158
}

‎src/platform/silabs/services/http_client.cpp‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,9 @@ sl_status_t HttpClient::GetResponseCallback(const sl_http_client_t * client, sl_
449449
sl_http_client_response_t * getResponse = static_cast<sl_http_client_response_t *>(data);
450450
self->mCallbackStatus = getResponse->status;
451451

452-
ChipLogProgress(DeviceLayer, "HTTPS GET response: status=0x%lX http_code=%u data_len=%u",
453-
static_cast<unsigned long>(getResponse->status), getResponse->http_response_code, getResponse->data_length);
452+
ChipLogProgress(DeviceLayer, "HTTPS GET response: status=0x%lX http_code=%u data_len=%u end_of_data=%lu",
453+
static_cast<unsigned long>(getResponse->status), getResponse->http_response_code, getResponse->data_length,
454+
static_cast<unsigned long>(getResponse->end_of_data));
454455

455456
if ((getResponse->status != SL_STATUS_OK) && (getResponse->status != SL_STATUS_IN_PROGRESS))
456457
{
@@ -469,6 +470,8 @@ sl_status_t HttpClient::GetResponseCallback(const sl_http_client_t * client, sl_
469470
return getResponse->status;
470471
}
471472

473+
self->mEndOfData = static_cast<EndOfData>(getResponse->end_of_data);
474+
472475
if (getResponse->data_length)
473476
{
474477
if (self->mActiveResponseBuffer != nullptr)
@@ -490,7 +493,7 @@ sl_status_t HttpClient::GetResponseCallback(const sl_http_client_t * client, sl_
490493
}
491494
}
492495

493-
if (getResponse->end_of_data)
496+
if (self->mEndOfData == EndOfData::EndOfData)
494497
{
495498
if (self->mActiveResponseBuffer != nullptr)
496499
{

‎src/platform/silabs/services/http_client.h‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ namespace Silabs {
4747
*/
4848
struct HttpClientConfig
4949
{
50-
uint8_t certificateIndex = 1; ///< NWP TLS / HTTPS certificate index.
51-
bool httpsEnable = true; ///< true = HTTPS, false = plain HTTP.
50+
uint8_t certificateIndex = SL_HTTPS_CLIENT_DEFAULT_CERTIFICATE_INDEX; ///< NWP TLS / HTTPS certificate index.
51+
bool httpsEnable = true; ///< true = HTTPS, false = plain HTTP.
5252
const char * username = nullptr; ///< Optional HTTP basic-auth username; nullptr skips auth.
5353
const char * password = nullptr; ///< Optional HTTP basic-auth password; nullptr skips auth.
5454

‎src/platform/silabs/services/matter_service.h‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,8 @@ namespace chip {
2424
namespace DeviceLayer {
2525
namespace Silabs {
2626

27-
namespace {
28-
/**
29-
* @brief Delay in seconds before initializing the Matter services.
30-
*/
27+
/** Delay before starting service demos after internet connectivity is established. */
3128
static constexpr uint32_t kMatterServicesInitDelaySec = 10;
32-
} // namespace
3329

3430
/**
3531
* @brief Common lifecycle for Matter platform services (HTTP, MQTT, ...).

‎src/platform/silabs/services/mqtt_client.cpp‎

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@
2626
#include <cstdlib>
2727
#include <cstring>
2828

29-
#ifndef MQTT_USE_HOST_LWIP_TLS
30-
#define MQTT_USE_HOST_LWIP_TLS 0
31-
#endif
32-
3329
namespace chip {
3430
namespace DeviceLayer {
3531
namespace Silabs {
@@ -154,7 +150,23 @@ void MqttClient::ServiceThread(void * arg)
154150
auto eventFlags = static_cast<osEventFlagsId_t>(self->mEventFlags);
155151
while (true)
156152
{
157-
uint32_t events = osEventFlagsWait(eventFlags, kEventOperation | kEventStop, osFlagsWaitAny, osWaitForever);
153+
// If the client is connected and not busy, wait for the idle yield timeout.
154+
// Otherwise, wait forever for an event.
155+
// This is to publish PINGREQ messages in the background to keep the connection alive.
156+
// idleYieldTimeoutMs cannot be greater than keepAliveIntervalSec * 1000 so PINGREQ can fire in time.
157+
158+
// TODO: revist this logic, since most of the calculations are done in the MQTTYield function.
159+
// so just invoking MQTTYield function here with (keepAliveIntervalSec *1000u - idleYieldTimeoutMs) value.
160+
// should be enough to keep the connection alive.
161+
const uint32_t waitMs = (self->mConnected && !self->mBusy) ? self->GetIdleYieldTimeoutMs() : osWaitForever;
162+
uint32_t events = osEventFlagsWait(eventFlags, kEventOperation | kEventStop, osFlagsWaitAny, waitMs);
163+
164+
if (events == osFlagsErrorTimeout)
165+
{
166+
self->IdleYield();
167+
continue;
168+
}
169+
158170
if (events & osFlagsError)
159171
{
160172
ChipLogError(DeviceLayer, "MQTT service event wait failed: 0x%lx", static_cast<unsigned long>(events));
@@ -176,6 +188,42 @@ void MqttClient::ServiceThread(void * arg)
176188
osThreadTerminate(osThreadGetId());
177189
}
178190

191+
uint32_t MqttClient::GetIdleYieldTimeoutMs()
192+
{
193+
// If the idle yield timeout is not set, use the default value of 1000 ms.
194+
// Though this is set in the constructor, it is possible to change the value later.
195+
if (mConfig.idleYieldTimeoutMs == 0)
196+
{
197+
ChipLogError(DeviceLayer, "MQTT idleYieldTimeoutMs is 0 (ignored); using default 1000 ms");
198+
mConfig.idleYieldTimeoutMs = 1000;
199+
}
200+
201+
const uint32_t configuredMs = mConfig.idleYieldTimeoutMs;
202+
203+
// MQTTYield timeout_ms must be <= keepAliveInterval * 1000 so PINGREQ can fire in time.
204+
VerifyOrReturnValue(mConfig.keepAliveIntervalSec > 0, configuredMs);
205+
206+
const uint32_t keepAliveMs = static_cast<uint32_t>(mConfig.keepAliveIntervalSec) * 1000u;
207+
return (configuredMs < keepAliveMs) ? configuredMs : keepAliveMs;
208+
}
209+
210+
void MqttClient::IdleYield()
211+
{
212+
VerifyOrReturn(mConnected && !mBusy);
213+
214+
const uint32_t yieldMs = GetIdleYieldTimeoutMs();
215+
const int status = MQTTYield(&mClient, static_cast<int>(yieldMs));
216+
if (status != SUCCESS)
217+
{
218+
ChipLogError(DeviceLayer, "MQTT idle Yield failed: %d (session marked disconnected)", status);
219+
CHIP_ERROR err = ProcessDisconnect();
220+
if (err != CHIP_NO_ERROR)
221+
{
222+
ChipLogError(DeviceLayer, "MQTT idle Yield disconnect failed: %" CHIP_ERROR_FORMAT, err.Format());
223+
}
224+
}
225+
}
226+
179227
CHIP_ERROR MqttClient::Start()
180228
{
181229
VerifyOrReturnError(mThreadId == nullptr, CHIP_NO_ERROR);
@@ -487,6 +535,11 @@ CHIP_ERROR MqttClient::ProcessYield()
487535
if (status != SUCCESS)
488536
{
489537
ChipLogError(DeviceLayer, "MQTT Yield failed: %d", status);
538+
CHIP_ERROR err = ProcessDisconnect();
539+
if (err != CHIP_NO_ERROR)
540+
{
541+
ChipLogError(DeviceLayer, "MQTT Yield disconnect failed: %" CHIP_ERROR_FORMAT, err.Format());
542+
}
490543
return MapPahoStatus(status);
491544
}
492545
return CHIP_NO_ERROR;

0 commit comments

Comments
 (0)