blob: 5981772d2258d0f9919a673e85d7b39518da80fd [file] [log] [blame]
/*
*
* Copyright (c) 2025 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 <AllDevicesExampleDeviceInfoProviderImpl.h>
#include <AppMainLoop.h>
#include <LinuxCommissionableDataProvider.h>
#include <TracingCommandLineArgument.h>
#include <app/persistence/DefaultAttributePersistenceProvider.h>
#include <app/server-cluster/ServerClusterInterfaceRegistry.h>
#include <app/server/Dnssd.h>
#include <app_options/AppOptions.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>
#include <devices/device-factory/DeviceFactory.h>
#include <devices/root-node/RootNodeDevice.h>
#include <platform/CommissionableDataProvider.h>
#include <platform/Linux/NetworkCommissioningDriver.h>
#include <platform/PlatformManager.h>
#include <setup_payload/OnboardingCodesUtil.h>
#include <string>
#include <system/SystemLayer.h>
using namespace chip;
using namespace chip::app;
using namespace chip::Platform;
using namespace chip::DeviceLayer;
using namespace chip::app::Clusters;
using namespace chip::ArgParser;
namespace {
AppMainLoopImplementation * gMainLoopImplementation = nullptr;
DeviceLayer::NetworkCommissioning::LinuxWiFiDriver sWiFiDriver;
AllDevicesExampleDeviceInfoProviderImpl gExampleDeviceInfoProvider;
// To hold SPAKE2+ verifier, discriminator, passcode
LinuxCommissionableDataProvider gCommissionableDataProvider;
void StopSignalHandler(int /* signal */)
{
if (gMainLoopImplementation != nullptr)
{
gMainLoopImplementation->SignalSafeStopMainLoop();
}
else
{
Server::GetInstance().GenerateShutDownEvent();
TEMPORARY_RETURN_IGNORED SystemLayer().ScheduleLambda([]() { TEMPORARY_RETURN_IGNORED PlatformMgr().StopEventLoopTask(); });
}
}
chip::app::DataModel::Provider * PopulateCodeDrivenDataModelProvider(PersistentStorageDelegate * delegate)
{
static chip::app::DefaultAttributePersistenceProvider attributePersistenceProvider;
static chip::app::CodeDrivenDataModelProvider dataModelProvider =
chip::app::CodeDrivenDataModelProvider(*delegate, attributePersistenceProvider);
static WifiRootNodeDevice rootNodeDevice(&sWiFiDriver);
static std::unique_ptr<DeviceInterface> constructedDevice;
TEMPORARY_RETURN_IGNORED rootNodeDevice.Register(kRootEndpointId, dataModelProvider, kInvalidEndpointId);
constructedDevice = DeviceFactory::GetInstance().Create(AppOptions::GetDeviceType());
TEMPORARY_RETURN_IGNORED constructedDevice->Register(AppOptions::GetDeviceEndpoint(), dataModelProvider, kInvalidEndpointId);
return &dataModelProvider;
}
void RunApplication(AppMainLoopImplementation * mainLoop = nullptr)
{
gMainLoopImplementation = mainLoop;
static chip::CommonCaseDeviceServerInitParams initParams;
VerifyOrDie(initParams.InitializeStaticResourcesBeforeServerInit() == CHIP_NO_ERROR);
initParams.dataModelProvider = PopulateCodeDrivenDataModelProvider(initParams.persistentStorageDelegate);
initParams.operationalServicePort = CHIP_PORT;
initParams.userDirectedCommissioningPort = CHIP_UDC_PORT;
initParams.interfaceId = Inet::InterfaceId::Null();
chip::CommandLineApp::TracingSetup tracing_setup;
tracing_setup.EnableTracingFor("json:log");
// Init ZCL Data Model and CHIP App Server
CHIP_ERROR err = Server::GetInstance().Init(initParams);
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "Server init failed: %" CHIP_ERROR_FORMAT, err.Format());
chipDie();
}
// Now that the server has started and we are done with our startup logging,
// log our discovery/onboarding information again so it's not lost in the
// noise.
ConfigurationMgr().LogDeviceConfig();
chip::PayloadContents payload;
payload.version = 0;
payload.rendezvousInformation.SetValue(RendezvousInformationFlag::kBLE);
if (GetCommissionableDataProvider()->GetSetupPasscode(payload.setUpPINCode) != CHIP_NO_ERROR)
{
payload.setUpPINCode = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE;
}
uint16_t discriminator = 0;
VerifyOrDie(GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator) == CHIP_NO_ERROR);
payload.discriminator.SetLongValue(discriminator);
VerifyOrDie(chip::DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(payload.vendorID) == CHIP_NO_ERROR);
VerifyOrDie(chip::DeviceLayer::GetDeviceInstanceInfoProvider()->GetProductId(payload.productID) == CHIP_NO_ERROR);
PrintOnboardingCodes(payload);
SetDeviceAttestationCredentialsProvider(Credentials::Examples::GetExampleDACProvider());
sWiFiDriver.Set5gSupport(true);
struct sigaction sa = {};
sa.sa_handler = StopSignalHandler;
sa.sa_flags = SA_RESETHAND;
sigaction(SIGINT, &sa, nullptr);
sigaction(SIGTERM, &sa, nullptr);
if (mainLoop != nullptr)
{
mainLoop->RunMainLoop();
}
else
{
DeviceLayer::PlatformMgr().RunEventLoop();
}
gMainLoopImplementation = nullptr;
Server::GetInstance().Shutdown();
DeviceLayer::PlatformMgr().Shutdown();
tracing_setup.StopTracing();
}
void EventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
{
(void) arg;
if (event->Type == DeviceLayer::DeviceEventType::kCHIPoBLEConnectionEstablished)
{
ChipLogProgress(DeviceLayer, "Receive kCHIPoBLEConnectionEstablished");
}
else if ((event->Type == chip::DeviceLayer::DeviceEventType::kInternetConnectivityChange))
{
// Restart the server on connectivity change
DnssdServer::Instance().StartServer();
}
}
CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & provider)
{
auto discriminator = static_cast<uint16_t>(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR);
chip::Optional<uint16_t> discriminatorFromParam = LinuxDeviceOptions::GetInstance().discriminator;
if (discriminatorFromParam.HasValue())
{
discriminator = discriminatorFromParam.Value();
}
const auto setupPasscode = MakeOptional(static_cast<uint32_t>(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE));
const uint32_t spake2pIterationCount = Crypto::kSpake2p_Min_PBKDF_Iterations;
Optional<std::vector<uint8_t>> serializedSpake2pVerifier = NullOptional;
Optional<std::vector<uint8_t>> spake2pSalt = NullOptional;
return provider.Init( //
serializedSpake2pVerifier, //
spake2pSalt, //
spake2pIterationCount, //
setupPasscode, //
discriminator //
);
}
CHIP_ERROR Initialize(int argc, char * argv[])
{
ChipLogProgress(AppServer, "Initializing...");
ReturnErrorOnFailure(Platform::MemoryInit());
ReturnErrorOnFailure(ParseArguments(argc, argv, AppOptions::GetOptions()));
ReturnErrorOnFailure(DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(CHIP_CONFIG_KVS_PATH));
ReturnErrorOnFailure(DeviceLayer::PlatformMgr().InitChipStack());
ReturnErrorOnFailure(InitCommissionableDataProvider(gCommissionableDataProvider));
DeviceLayer::SetCommissionableDataProvider(&gCommissionableDataProvider);
DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
ConfigurationMgr().LogDeviceConfig();
ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(EventHandler, 0));
ReturnErrorOnFailure(DeviceLayer::ConnectivityMgr().SetBLEDeviceName(nullptr));
ReturnErrorOnFailure(DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(0, false));
ReturnErrorOnFailure(DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(true));
return CHIP_NO_ERROR;
}
} // namespace
void ApplicationShutdown() {}
int main(int argc, char * argv[])
{
ChipLogProgress(AppServer, "Initializing");
if (CHIP_ERROR err = Initialize(argc, argv); err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "Initialize() failed: %" CHIP_ERROR_FORMAT, err.Format());
chipDie();
}
ChipLogProgress(AppServer, "Hello from all-devices-app!");
RunApplication();
return 0;
}