diff --git a/examples/tv-casting-app/linux/simple-app.cpp b/examples/tv-casting-app/linux/simple-app.cpp index 26f9e2825ff7d9..cd2f71eb612159 100644 --- a/examples/tv-casting-app/linux/simple-app.cpp +++ b/examples/tv-casting-app/linux/simple-app.cpp @@ -16,6 +16,8 @@ * limitations under the License. */ +#include "core/CastingPlayer.h" +#include "core/CastingPlayerDiscovery.h" #include "core/Types.h" #include @@ -76,6 +78,33 @@ CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & prov options.payload.discriminator.GetLongValue()); } +/** + * @brief React to discovery results + */ +class DiscoveryDelegateImpl : public DiscoveryDelegate +{ +private: + int commissionersCount = 0; + +public: + void HandleOnAdded(matter::casting::memory::Strong player) override + { + if (commissionersCount == 0) + { + ChipLogProgress(AppServer, "Select discovered CastingPlayer to request commissioning"); + + ChipLogProgress(AppServer, "Example: cast request 0"); + } + ++commissionersCount; + ChipLogProgress(AppServer, "Discovered CastingPlayer #%d", commissionersCount); + player->LogDetail(); + } + void HandleOnUpdated(matter::casting::memory::Strong player) override + { + ChipLogProgress(AppServer, "Updated CastingPlayer with ID: %s", player->GetId()); + } +}; + /** * @brief Provides the unique ID that is used by the SDK to generate the Rotating Device ID. */ @@ -148,6 +177,17 @@ int main(int argc, char * argv[]) VerifyOrReturnValue(err == CHIP_NO_ERROR, 0, ChipLogError(AppServer, "CastingApp::Start failed %" CHIP_ERROR_FORMAT, err.Format())); + DiscoveryDelegateImpl delegate; + CastingPlayerDiscovery::GetInstance()->SetDelegate(&delegate); + VerifyOrReturnValue(err == CHIP_NO_ERROR, 0, + ChipLogError(AppServer, "CastingPlayerDiscovery::SetDelegate failed %" CHIP_ERROR_FORMAT, err.Format())); + + // Discover CastingPlayers + const uint64_t kTargetPlayerDeviceType = 35; // 35 represents device type of Matter Video Player + err = CastingPlayerDiscovery::GetInstance()->StartDiscovery(kTargetPlayerDeviceType); + VerifyOrReturnValue(err == CHIP_NO_ERROR, 0, + ChipLogError(AppServer, "CastingPlayerDiscovery::StartDiscovery failed %" CHIP_ERROR_FORMAT, err.Format())); + chip::DeviceLayer::PlatformMgr().RunEventLoop(); return 0; diff --git a/examples/tv-casting-app/tv-casting-common/BUILD.gn b/examples/tv-casting-app/tv-casting-common/BUILD.gn index 115a0b7e4bbfb0..f555a62a181a41 100644 --- a/examples/tv-casting-app/tv-casting-common/BUILD.gn +++ b/examples/tv-casting-app/tv-casting-common/BUILD.gn @@ -89,6 +89,9 @@ chip_data_model("tv-casting-common") { sources += [ "core/CastingApp.cpp", "core/CastingApp.h", + "core/CastingPlayer.h", + "core/CastingPlayerDiscovery.cpp", + "core/CastingPlayerDiscovery.h", "core/Types.h", "support/AppParameters.h", "support/DataProvider.h", diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp index f8d66b03e0ac0c..bc495a27fff870 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp @@ -44,7 +44,7 @@ CastingApp * CastingApp::GetInstance() CHIP_ERROR CastingApp::Initialize(const AppParameters & appParameters) { - VerifyOrReturnError(mState == UNINITIALIZED, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mState == CASTING_APP_UNINITIALIZED, CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(appParameters.GetCommissionableDataProvider() != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(appParameters.GetDeviceAttestationCredentialsProvider() != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(appParameters.GetServerInitParamsProvider() != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -74,14 +74,14 @@ CHIP_ERROR CastingApp::Initialize(const AppParameters & appParameters) } #endif // CHIP_ENABLE_ROTATING_DEVICE_ID - mState = NOT_RUNNING; // initialization done, set state to NOT_RUNNING + mState = CASTING_APP_NOT_RUNNING; // initialization done, set state to NOT_RUNNING return CHIP_NO_ERROR; } CHIP_ERROR CastingApp::Start() { - VerifyOrReturnError(mState == NOT_RUNNING, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mState == CASTING_APP_NOT_RUNNING, CHIP_ERROR_INCORRECT_STATE); // start Matter server chip::ServerInitParams * serverInitParams = mAppParameters->GetServerInitParamsProvider()->Get(); @@ -96,7 +96,7 @@ CHIP_ERROR CastingApp::Start() CHIP_ERROR CastingApp::PostStartRegistrations() { - VerifyOrReturnError(mState == NOT_RUNNING, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mState == CASTING_APP_NOT_RUNNING, CHIP_ERROR_INCORRECT_STATE); auto & server = chip::Server::GetInstance(); // TODO: Set CastingApp as AppDelegate @@ -112,13 +112,13 @@ CHIP_ERROR CastingApp::PostStartRegistrations() // TODO: Add DeviceEvent Handler // ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(DeviceEventCallback, 0)); - mState = RUNNING; // CastingApp started successfully, set state to RUNNING + mState = CASTING_APP_RUNNING; // CastingApp started successfully, set state to RUNNING return CHIP_NO_ERROR; } CHIP_ERROR CastingApp::Stop() { - VerifyOrReturnError(mState == RUNNING, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mState == CASTING_APP_RUNNING, CHIP_ERROR_INCORRECT_STATE); // TODO: add logic to capture CastingPlayers that we are currently connected to, so we can automatically reconnect with them on // Start() again @@ -126,7 +126,7 @@ CHIP_ERROR CastingApp::Stop() // Shutdown the Matter server chip::Server::GetInstance().Shutdown(); - mState = NOT_RUNNING; // CastingApp stopped successfully, set state to NOT_RUNNING + mState = CASTING_APP_NOT_RUNNING; // CastingApp stopped successfully, set state to NOT_RUNNING return CHIP_ERROR_NOT_IMPLEMENTED; } diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingApp.h b/examples/tv-casting-app/tv-casting-common/core/CastingApp.h index eed69e728d4358..e66283c3fb1c9d 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingApp.h +++ b/examples/tv-casting-app/tv-casting-common/core/CastingApp.h @@ -30,9 +30,9 @@ namespace core { */ enum CastingAppState { - UNINITIALIZED, // Before Initialize() success - NOT_RUNNING, // After Initialize() success before Start()ing, OR After stop() success - RUNNING, // After Start() success + CASTING_APP_UNINITIALIZED, // Before Initialize() success + CASTING_APP_NOT_RUNNING, // After Initialize() success before Start()ing, OR After stop() success + CASTING_APP_RUNNING, // After Start() success }; /** @@ -83,7 +83,7 @@ class CastingApp const matter::casting::support::AppParameters * mAppParameters; - CastingAppState mState = UNINITIALIZED; + CastingAppState mState = CASTING_APP_UNINITIALIZED; }; }; // namespace core diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h new file mode 100644 index 00000000000000..ea407f2c0fca12 --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h @@ -0,0 +1,168 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Types.h" +#include "lib/support/logging/CHIPLogging.h" + +#include +#include +#include +#include + +namespace matter { +namespace casting { +namespace core { + +enum ConnectionError +{ + NO_CONNECTION_ERROR = 0, + FAILED_TO_CONNECT = 1 +}; + +using ConnectCallback = std::function; +using DisconnectCallback = std::function; + +const int kPortMaxLength = 5; // port is uint16_t +const int kIdMaxLength = chip::Dnssd::kHostNameMaxLength + kPortMaxLength; + +class Attributes +{ +public: + char id[kIdMaxLength] = {}; + char deviceName[chip::Dnssd::kMaxDeviceNameLen + 1] = {}; + char hostName[chip::Dnssd::kHostNameMaxLength + 1] = {}; + char instanceName[chip::Dnssd::kHostNameMaxLength + 1] = {}; + unsigned int numIPs; // number of valid IP addresses + chip::Inet::IPAddress ipAddresses[chip::Dnssd::CommonResolutionData::kMaxIPAddresses]; + uint16_t port; + uint16_t productId; + uint16_t vendorId; + uint32_t deviceType; +}; + +/** + * @brief CastingPlayer represents a Matter commissioner that is able to play media to a physical + * output or to a display screen which is part of the device. + */ +class CastingPlayer : public std::enable_shared_from_this +{ +private: + // std::vector> endpoints; + bool mConnected = false; + Attributes mAttributes; + +public: + CastingPlayer(Attributes playerAttributes) { mAttributes = playerAttributes; } + const char * GetId() const { return mAttributes.id; } + + const char * GetDeviceName() const { return mAttributes.deviceName; } + + const char * GetHostName() const { return mAttributes.hostName; } + + const char * GetInstanceName() const { return mAttributes.instanceName; } + + uint GetNumIPs() const { return mAttributes.numIPs; } + + chip::Inet::IPAddress * GetIPAddresses() { return mAttributes.ipAddresses; } + + uint16_t GetPort() { return mAttributes.port; } + + uint16_t GetProductId() const { return mAttributes.productId; } + + uint16_t GetVendorId() const { return mAttributes.vendorId; } + + uint32_t GetDeviceType() const { return mAttributes.deviceType; } + + // public: + // void RegisterEndpoint(const memory::Strong endpoint) { endpoints.push_back(endpoint); } + + // const std::vector> GetEndpoints() const { return endpoints; } + + /** + * @brief Compares based on the Id + */ + bool operator==(const CastingPlayer & other) const + { + int compareResult = strcmp(this->mAttributes.id, other.mAttributes.id); + return (compareResult == 0) ? 1 : 0; + } + +public: + /** + * @return true if this CastingPlayer is connected to the CastingApp + */ + bool IsConnected() const { return mConnected; } + + void Connect(const long timeout, ConnectCallback onCompleted); + void Disconnect(const long timeout, DisconnectCallback onCompleted); + + void LogDetail() const + { + if (strlen(mAttributes.id) != 0) + { + ChipLogDetail(Discovery, "\tID: %s", mAttributes.id); + } + if (strlen(mAttributes.deviceName) != 0) + { + ChipLogDetail(Discovery, "\tName: %s", mAttributes.deviceName); + } + if (strlen(mAttributes.hostName) != 0) + { + ChipLogDetail(Discovery, "\tHost Name: %s", mAttributes.hostName); + } + if (strlen(mAttributes.instanceName) != 0) + { + ChipLogDetail(Discovery, "\tInstance Name: %s", mAttributes.instanceName); + } + if (mAttributes.numIPs > 0) + { + ChipLogDetail(Discovery, "\tNumber of IPs: %u", mAttributes.numIPs); + } + char buf[chip::Inet::IPAddress::kMaxStringLength]; + if (strlen(mAttributes.ipAddresses[0].ToString(buf)) != 0) + { + for (unsigned j = 0; j < mAttributes.numIPs; j++) + { + char * ipAddressOut = mAttributes.ipAddresses[j].ToString(buf); + ChipLogDetail(AppServer, "\tIP Address #%d: %s", j + 1, ipAddressOut); + } + } + if (mAttributes.port > 0) + { + ChipLogDetail(Discovery, "\tPort: %u", mAttributes.port); + } + if (mAttributes.productId > 0) + { + ChipLogDetail(Discovery, "\tProduct ID: %u", mAttributes.productId); + } + if (mAttributes.vendorId > 0) + { + ChipLogDetail(Discovery, "\tVendor ID: %u", mAttributes.vendorId); + } + if (mAttributes.deviceType > 0) + { + ChipLogDetail(Discovery, "\tDevice Type: %" PRIu32, mAttributes.deviceType); + } + } +}; + +}; // namespace core +}; // namespace casting +}; // namespace matter diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.cpp new file mode 100644 index 00000000000000..fe247e0d47f5d6 --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.cpp @@ -0,0 +1,132 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CastingPlayerDiscovery.h" + +namespace matter { +namespace casting { +namespace core { + +using namespace chip::System; +using namespace chip::Controller; +using namespace chip::Dnssd; +using namespace std; + +CastingPlayerDiscovery * CastingPlayerDiscovery::_castingPlayerDiscovery = nullptr; + +CastingPlayerDiscovery::CastingPlayerDiscovery() {} + +CastingPlayerDiscovery * CastingPlayerDiscovery::GetInstance() +{ + if (_castingPlayerDiscovery == nullptr) + { + _castingPlayerDiscovery = new CastingPlayerDiscovery(); + } + return _castingPlayerDiscovery; +} + +CHIP_ERROR CastingPlayerDiscovery::StartDiscovery(uint64_t deviceTypeFilter) +{ + ChipLogProgress(Discovery, "CastingPlayerDiscovery::StartDiscovery called"); + VerifyOrReturnError(mState == DISCOVERY_READY, CHIP_ERROR_INCORRECT_STATE); + + mCommissionableNodeController.RegisterDeviceDiscoveryDelegate(&mDelegate); + + if (deviceTypeFilter > 0) + { + ReturnErrorOnFailure(mCommissionableNodeController.DiscoverCommissioners( + DiscoveryFilter(DiscoveryFilterType::kDeviceType, deviceTypeFilter))); + } + else + { + ReturnErrorOnFailure(mCommissionableNodeController.DiscoverCommissioners()); + } + + mState = DISCOVERY_RUNNING; + return CHIP_NO_ERROR; +} + +CHIP_ERROR CastingPlayerDiscovery::StopDiscovery() +{ + VerifyOrReturnError(mState == DISCOVERY_RUNNING, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(mCommissionableNodeController.StopDiscovery()); + + mState = DISCOVERY_READY; + + return CHIP_NO_ERROR; +} + +void DeviceDiscoveryDelegateImpl::OnDiscoveredDevice(const chip::Dnssd::DiscoveredNodeData & nodeData) +{ + ChipLogProgress(Discovery, "DeviceDiscoveryDelegateImpl::OnDiscoveredDevice called"); + VerifyOrReturn(mClientDelegate != nullptr, + ChipLogError(NotSpecified, "CastingPlayerDeviceDiscoveryDelegate, mClientDelegate is a nullptr")); + + // convert nodeData to CastingPlayer + Attributes attributes; + strcpy(attributes.id, nodeData.resolutionData.hostName); + + char port[kPortMaxLength] = {}; + snprintf(port, sizeof(port), "%u", nodeData.resolutionData.port); + strcat(attributes.id, port); + + strcpy(attributes.deviceName, nodeData.commissionData.deviceName); + strcpy(attributes.hostName, nodeData.resolutionData.hostName); + strcpy(attributes.instanceName, nodeData.commissionData.instanceName); + attributes.numIPs = (unsigned int) nodeData.resolutionData.numIPs; + for (unsigned j = 0; j < attributes.numIPs; j++) + { + attributes.ipAddresses[j] = nodeData.resolutionData.ipAddress[j]; + } + attributes.port = nodeData.resolutionData.port; + attributes.productId = nodeData.commissionData.productId; + attributes.vendorId = nodeData.commissionData.vendorId; + attributes.deviceType = nodeData.commissionData.deviceType; + + memory::Strong player = std::make_shared(attributes); + + std::vector> castingPlayers = CastingPlayerDiscovery::GetInstance()->GetCastingPlayers(); + + // Add to or update castingPlayers + if (castingPlayers.size() != 0) + { + auto it = + std::find_if(castingPlayers.begin(), castingPlayers.end(), + [&player](const memory::Strong & castingPlayer) { return *castingPlayer == *player; }); + + // ID match found in castingPlayer, perfom update + if (it != castingPlayers.end()) + { + unsigned index = (unsigned int) std::distance(castingPlayers.begin(), it); + castingPlayers[index] = player; + CastingPlayerDiscovery::GetInstance()->mCastingPlayers = castingPlayers; + ChipLogProgress(AppServer, "Updated Casting Player"); + + mClientDelegate->HandleOnUpdated(player); + return; + } + } + + castingPlayers.push_back(player); + CastingPlayerDiscovery::GetInstance()->mCastingPlayers = castingPlayers; + mClientDelegate->HandleOnAdded(player); +} + +}; // namespace core +}; // namespace casting +}; // namespace matter diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.h b/examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.h new file mode 100644 index 00000000000000..1c2d3fe1c71033 --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayerDiscovery.h @@ -0,0 +1,133 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "CastingPlayer.h" +#include "Types.h" + +#include +#include +#include + +namespace matter { +namespace casting { +namespace core { + +/** + * @brief Represents CastingPlayerDiscovery state. + * + */ +enum CastingPlayerDiscoveryState +{ + DISCOVERY_NOT_READY, // Default state, mClientDelegate isn't initialized + DISCOVERY_READY, // After SetDelegate and before StartDiscovery, mClientDelegate is initialized + DISCOVERY_RUNNING, // After StartDiscovery success +}; + +/** + * @brief DiscoveryDelegate handles callbacks as CastingPlayers are discovered, updated, or lost + * from the network. + */ +class DLL_EXPORT DiscoveryDelegate +{ +public: + virtual ~DiscoveryDelegate() {} + virtual void HandleOnAdded(memory::Strong player) = 0; + virtual void HandleOnUpdated(memory::Strong players) = 0; + // virtual void HandleOnRemoved(memory::Strong players) = 0; +}; + +class CastingPlayerDiscovery; + +/** + * @brief DeviceDiscoveryDelegateImpl defines functionality for when callback + * OnDiscoveredDevice is called. + */ +class DeviceDiscoveryDelegateImpl : public chip::Controller::DeviceDiscoveryDelegate +{ +private: + DiscoveryDelegate * mClientDelegate = nullptr; + +public: + DeviceDiscoveryDelegateImpl() {} + DeviceDiscoveryDelegateImpl(DiscoveryDelegate * delegate) { mClientDelegate = delegate; } + + void OnDiscoveredDevice(const chip::Dnssd::DiscoveredNodeData & nodeData) override; +}; + +/** + * @brief CastingPlayerDiscovery represents the discovery of Casting Players. + * This class is a singleton. + */ +class CastingPlayerDiscovery +{ + +private: + std::vector> mCastingPlayers; + DeviceDiscoveryDelegateImpl mDelegate; + + CastingPlayerDiscovery(); + static CastingPlayerDiscovery * _castingPlayerDiscovery; + + CastingPlayerDiscovery(CastingPlayerDiscovery & other) = delete; + void operator=(const CastingPlayerDiscovery &) = delete; + + chip::Controller::CommissionableNodeController mCommissionableNodeController; + CastingPlayerDiscoveryState mState = DISCOVERY_NOT_READY; + +public: + static CastingPlayerDiscovery * GetInstance(); + + /** + * @brief Starts the discovery for CastingPlayers + * + * @param filterBydeviceType if passed as a non-zero value, CastingPlayerDiscovery will only callback on the DiscoveryDelegate + * with CastingPlayers whose deviceType matches filterBydeviceType + * @return CHIP_ERROR - CHIP_NO_ERROR if discovery for CastingPlayers started successfully, specific error code otherwise. + */ + CHIP_ERROR StartDiscovery(uint64_t filterBydeviceType = 0); + + /** + * @brief Stop the discovery for CastingPlayers + * + * @return CHIP_ERROR - CHIP_NO_ERROR if discovery for CastingPlayers stopped successfully, specific error code otherwise. + */ + CHIP_ERROR StopDiscovery(); + + void SetDelegate(DiscoveryDelegate * clientDelegate) + { + if (clientDelegate == nullptr) + { + mState = DISCOVERY_NOT_READY; + } + else + { + mState = DISCOVERY_READY; + } + mDelegate = DeviceDiscoveryDelegateImpl(clientDelegate); + } + + std::vector> GetCastingPlayers() { return mCastingPlayers; } + + friend class DeviceDiscoveryDelegateImpl; +}; + +}; // namespace core +}; // namespace casting +}; // namespace matter diff --git a/src/controller/AbstractDnssdDiscoveryController.h b/src/controller/AbstractDnssdDiscoveryController.h index 55e148f68d21af..788102282bd86d 100644 --- a/src/controller/AbstractDnssdDiscoveryController.h +++ b/src/controller/AbstractDnssdDiscoveryController.h @@ -43,6 +43,7 @@ class DLL_EXPORT AbstractDnssdDiscoveryController : public Dnssd::CommissioningR ~AbstractDnssdDiscoveryController() override { mDNSResolver.Shutdown(); } void OnNodeDiscovered(const chip::Dnssd::DiscoveredNodeData & nodeData) override; + CHIP_ERROR StopDiscovery() { return mDNSResolver.StopDiscovery(); }; protected: using DiscoveredNodeList = FixedSpan; diff --git a/src/controller/CHIPCommissionableNodeController.cpp b/src/controller/CHIPCommissionableNodeController.cpp index 67e6ce8065c29a..fdcf1f7e2649b9 100644 --- a/src/controller/CHIPCommissionableNodeController.cpp +++ b/src/controller/CHIPCommissionableNodeController.cpp @@ -48,6 +48,16 @@ CHIP_ERROR CommissionableNodeController::DiscoverCommissioners(Dnssd::DiscoveryF return mResolver->DiscoverCommissioners(discoveryFilter); } +CHIP_ERROR CommissionableNodeController::StopDiscovery() +{ + if (mResolver == nullptr) + { + return AbstractDnssdDiscoveryController::StopDiscovery(); + } + + return mResolver->StopDiscovery(); +} + CommissionableNodeController::~CommissionableNodeController() { mDNSResolver.SetCommissioningDelegate(nullptr); diff --git a/src/controller/CHIPCommissionableNodeController.h b/src/controller/CHIPCommissionableNodeController.h index a31e14309af367..e573ba6fc4b5e9 100644 --- a/src/controller/CHIPCommissionableNodeController.h +++ b/src/controller/CHIPCommissionableNodeController.h @@ -42,6 +42,8 @@ class DLL_EXPORT CommissionableNodeController : public AbstractDnssdDiscoveryCon void RegisterDeviceDiscoveryDelegate(DeviceDiscoveryDelegate * delegate) { mDeviceDiscoveryDelegate = delegate; } CHIP_ERROR DiscoverCommissioners(Dnssd::DiscoveryFilter discoveryFilter = Dnssd::DiscoveryFilter()); + CHIP_ERROR StopDiscovery(); + /** * @return * Pointer to DiscoveredNodeData at index idx in the list of commissioners discovered