/* * * Copyright (c) 2023-2024 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 "CastingApp.h" #include "CommissionerDeclarationHandler.h" #include "ConnectionCallbacks.h" #include "support/CastingStore.h" #include "support/ChipDeviceEventHandler.h" #include #include #include #include #include namespace matter { namespace casting { namespace core { using namespace matter::casting::support; CastingApp * CastingApp::_castingApp = nullptr; CastingApp::CastingApp() {} CastingApp * CastingApp::GetInstance() { if (_castingApp == nullptr) { _castingApp = new CastingApp(); } return _castingApp; } CHIP_ERROR CastingApp::Initialize(const AppParameters & appParameters) { ChipLogProgress(Discovery, "CastingApp::Initialize() called"); 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); ReturnErrorOnFailure(chip::Platform::MemoryInit()); ReturnErrorOnFailure(chip::DeviceLayer::PlatformMgr().InitChipStack()); mAppParameters = &appParameters; chip::DeviceLayer::SetCommissionableDataProvider(appParameters.GetCommissionableDataProvider()); chip::Credentials::SetDeviceAttestationCredentialsProvider(appParameters.GetDeviceAttestationCredentialsProvider()); chip::Credentials::SetDeviceAttestationVerifier(appParameters.GetDeviceAttestationVerifier()); #if CHIP_ENABLE_ROTATING_DEVICE_ID MutableByteSpanDataProvider * uniqueIdProvider = appParameters.GetRotatingDeviceIdUniqueIdProvider(); if (uniqueIdProvider != nullptr) { chip::MutableByteSpan * uniqueId = uniqueIdProvider->Get(); if (uniqueId != nullptr) { ReturnErrorOnFailure(chip::DeviceLayer::ConfigurationMgr().SetRotatingDeviceIdUniqueId(*uniqueId)); } else { return CHIP_ERROR_INVALID_ARGUMENT; } } #endif // CHIP_ENABLE_ROTATING_DEVICE_ID mState = CASTING_APP_NOT_RUNNING; // initialization done, set state to NOT_RUNNING return CHIP_NO_ERROR; } CHIP_ERROR CastingApp::UpdateCommissionableDataProvider(chip::DeviceLayer::CommissionableDataProvider * commissionableDataProvider) { ChipLogProgress(Discovery, "CastingApp::UpdateCommissionableDataProvider()"); chip::DeviceLayer::SetCommissionableDataProvider(commissionableDataProvider); return mAppParameters->SetCommissionableDataProvider(commissionableDataProvider); } void ReconnectHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) { if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "CastingApp::ConnectionHandler() Could not reconnect to CastingPlayer %" CHIP_ERROR_FORMAT, err.Format()); } else { ChipLogProgress(AppServer, "CastingApp::ConnectionHandler() Reconnected to CastingPlayer(ID: %s)", castingPlayer->GetId()); } } CHIP_ERROR CastingApp::Start() { ChipLogProgress(Discovery, "CastingApp::Start()"); VerifyOrReturnError(mState == CASTING_APP_NOT_RUNNING, CHIP_ERROR_INCORRECT_STATE); // Start Matter server chip::ServerInitParams * serverInitParams = mAppParameters->GetServerInitParamsProvider()->Get(); VerifyOrReturnError(serverInitParams != nullptr, CHIP_ERROR_INVALID_ARGUMENT); ReturnErrorOnFailure(chip::Server::GetInstance().Init(*serverInitParams)); // Perform post server startup registrations ReturnErrorOnFailure(PostStartRegistrations()); // Reconnect (or verify connection) to the CastingPlayer that the app was connected to before being stopped, if any if (CastingPlayer::GetTargetCastingPlayer() != nullptr) { matter::casting::core::ConnectionCallbacks connectionCallbacks; connectionCallbacks.mOnConnectionComplete = ReconnectHandler; // Re-connecting to a CastingPLayer does not require a full User Directed Commissioning (UDC) process so // CommissionerDeclaration messages are not expected. Leaving ConnectionCallbacks mCommissionerDeclarationCallback as // nullptr. ChipLogProgress( Discovery, "CastingApp::Start() calling VerifyOrEstablishConnection() to reconnect (or verify connection) to a CastingPlayer"); CastingPlayer::GetTargetCastingPlayer()->VerifyOrEstablishConnection(connectionCallbacks); } return CHIP_NO_ERROR; } CHIP_ERROR CastingApp::PostStartRegistrations() { ChipLogProgress(Discovery, "CastingApp::PostStartRegistrations()"); VerifyOrReturnError(mState == CASTING_APP_NOT_RUNNING, CHIP_ERROR_INCORRECT_STATE); auto & server = chip::Server::GetInstance(); // TODO: Set CastingApp as AppDelegate // &server.GetCommissioningWindowManager().SetAppDelegate(??); // Initialize binding handlers chip::BindingManager::GetInstance().Init( { &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() }); // Set FabricDelegate chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(support::CastingStore::GetInstance()); // Register DeviceEvent Handler ReturnErrorOnFailure(chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(ChipDeviceEventHandler::Handle, 0)); ChipLogProgress( Discovery, "CastingApp::PostStartRegistrations() calling GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler()"); #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT // Set a handler for Commissioner's CommissionerDeclaration messages. This is set in // connectedhomeip/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler( CommissionerDeclarationHandler::GetInstance()); #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT mState = CASTING_APP_RUNNING; // CastingApp started successfully, set state to RUNNING return CHIP_NO_ERROR; } CHIP_ERROR CastingApp::Stop() { ChipLogProgress(Discovery, "CastingApp::Stop()"); VerifyOrReturnError(mState == CASTING_APP_RUNNING, CHIP_ERROR_INCORRECT_STATE); #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT // Remove the handler previously set for Commissioner's CommissionerDeclaration messages. chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler(nullptr); #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT // Shutdown the Matter server chip::Server::GetInstance().Shutdown(); mState = CASTING_APP_NOT_RUNNING; // CastingApp stopped successfully, set state to NOT_RUNNING return CHIP_NO_ERROR; } CHIP_ERROR CastingApp::ShutdownAllSubscriptions() { chip::app::InteractionModelEngine::GetInstance()->ShutdownAllSubscriptions(); return CHIP_NO_ERROR; } CHIP_ERROR CastingApp::ClearCache() { return support::CastingStore::GetInstance()->DeleteAll(); } }; // namespace core }; // namespace casting }; // namespace matter