blob: 7560f27a7c363cad6964642f0ef03cee99c7370f [file]
/*
*
* 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 "AppKeys.h"
#ifdef ENABLE_CHIP_SHELL
#include <DeviceShellCommands.h>
#endif
#include <cstring>
#include <memory>
#include <string>
#include <app/DefaultSafeAttributePersistenceProvider.h>
#include <app/persistence/DefaultAttributePersistenceProvider.h>
#include <app/EventManagement.h>
#include <app/InteractionModelEngine.h>
#include <app/server/Dnssd.h>
#include <app/server/Server.h>
#include <platform/CHIPDeviceLayer.h>
#include <setup_payload/OnboardingCodesUtil.h>
#include <device-factory/DeviceFactory.h>
#include <device/api/allocator/ConsecutiveEndpointIdAllocator.h>
#include <device/types/root-node/RootNode.h>
#if CHIP_ENABLE_OPENTHREAD
#include <device/types/root-node/ThreadRootNode.h>
#include <platform/NetworkCommissioning.h>
#endif
#if defined(CHIP_DEVICE_CONFIG_ENABLE_WIFI) && CHIP_DEVICE_CONFIG_ENABLE_WIFI
#include <device/types/root-node/WifiRootNode.h> // nogncheck
#include <platform/silabs/NetworkCommissioningWiFiDriver.h> // nogncheck
#endif
#include <platform/silabs/platformAbstraction/SilabsPlatform.h>
#define APP_FUNCTION_BUTTON 0
using namespace chip;
using namespace chip::app;
using namespace ::chip::DeviceLayer;
using namespace ::chip::DeviceLayer::Silabs;
namespace {
chip::app::DefaultAttributePersistenceProvider sAttributePersistenceProvider;
chip::app::DefaultSafeAttributePersistenceProvider sSafeAttributePersistenceProvider;
std::unique_ptr<chip::app::CodeDrivenDataModelProvider> sDataModelProvider;
std::unique_ptr<chip::app::DeviceInterface> sRootNode;
std::unique_ptr<chip::app::DeviceInterface> sConstructedDevice;
#if CHIP_ENABLE_OPENTHREAD
chip::DeviceLayer::NetworkCommissioning::GenericThreadDriver sThreadDriver;
#endif
constexpr chip::EndpointId kDeviceEndpointId = 1;
} // namespace
AppTask AppTask::sAppTask;
CHIP_ERROR AppTask::StartAppTask()
{
return BaseApplication::StartAppTask(AppTaskMain);
}
void AppTask::AppTaskMain(void * pvParameter)
{
AppEvent event;
osMessageQueueId_t sAppEventQueue = *(static_cast<osMessageQueueId_t *>(pvParameter));
CHIP_ERROR err = GetAppTask().Init();
if (err != CHIP_NO_ERROR)
{
SILABS_LOG("AppTask.Init() failed");
appError(err);
}
GetAppTask().StartStatusLEDTimer();
SILABS_LOG("App Task started");
while (true)
{
osStatus_t eventReceived = osMessageQueueGet(sAppEventQueue, &event, nullptr, osWaitForever);
while (eventReceived == osOK)
{
GetAppTask().DispatchEvent(&event);
eventReceived = osMessageQueueGet(sAppEventQueue, &event, nullptr, 0);
}
}
}
CHIP_ERROR AppTask::AppInit()
{
chip::DeviceLayer::Silabs::GetPlatform().SetButtonsCb(&AppTask::ButtonEventHandler);
#ifdef ENABLE_CHIP_SHELL
chip::Shell::DeviceCommands::GetInstance().Register();
#endif
return CHIP_NO_ERROR;
}
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 == APP_FUNCTION_BUTTON)
{
button_event.Handler = BaseApplication::ButtonHandler;
GetAppTask().PostEvent(&button_event);
}
}
CHIP_ERROR AppTask::InitCodeDrivenDataModel(chip::PersistentStorageDelegate & storage,
chip::Credentials::GroupDataProvider * groupDataProvider)
{
ReturnErrorOnFailure(sAttributePersistenceProvider.Init(&storage));
ReturnErrorOnFailure(sSafeAttributePersistenceProvider.Init(&storage));
chip::app::SetSafeAttributePersistenceProvider(&sSafeAttributePersistenceProvider);
sDataModelProvider = std::make_unique<chip::app::CodeDrivenDataModelProvider>(storage, sAttributePersistenceProvider);
VerifyOrReturnError(sDataModelProvider != nullptr, CHIP_ERROR_NO_MEMORY);
chip::DeviceLayer::DeviceInstanceInfoProvider * deviceInfoProvider = chip::DeviceLayer::GetDeviceInstanceInfoProvider();
VerifyOrReturnError(deviceInfoProvider != nullptr, CHIP_ERROR_INCORRECT_STATE);
static chip::app::DefaultTimerDelegate sTimerDelegate;
chip::app::RootNode::Context rootNodeContext = {
.commissioningWindowManager = chip::Server::GetInstance().GetCommissioningWindowManager(),
.configurationManager = chip::DeviceLayer::ConfigurationMgr(),
.deviceControlServer = chip::DeviceLayer::DeviceControlServer::DeviceControlSvr(),
.fabricTable = chip::Server::GetInstance().GetFabricTable(),
.accessControl = chip::Server::GetInstance().GetAccessControl(),
.persistentStorage = storage,
.failSafeContext = chip::Server::GetInstance().GetFailSafeContext(),
.deviceInstanceInfoProvider = *deviceInfoProvider,
.platformManager = chip::DeviceLayer::PlatformMgr(),
.groupDataProvider = *groupDataProvider,
.sessionManager = chip::Server::GetInstance().GetSecureSessionManager(),
.dnssdServer = chip::app::DnssdServer::Instance(),
.deviceLoadStatusProvider = *chip::app::InteractionModelEngine::GetInstance(),
.diagnosticDataProvider = chip::DeviceLayer::GetDiagnosticDataProvider(),
.testEventTriggerDelegate = nullptr,
.dacProvider = *chip::Credentials::GetDeviceAttestationCredentialsProvider(),
.eventManagement = chip::app::EventManagement::GetInstance(),
.timerDelegate = sTimerDelegate,
};
#if CHIP_ENABLE_OPENTHREAD
sRootNode = std::make_unique<chip::app::ThreadRootNode>(rootNodeContext,
chip::app::ThreadRootNode::ThreadContext{
.threadDriver = sThreadDriver,
});
#elif defined(CHIP_DEVICE_CONFIG_ENABLE_WIFI) && CHIP_DEVICE_CONFIG_ENABLE_WIFI
sRootNode = std::make_unique<chip::app::WifiRootNode>(
rootNodeContext,
chip::app::WifiRootNode::WifiContext{
.wifiDriver = *chip::DeviceLayer::NetworkCommissioning::SlWiFiDriver::GetInstance(),
});
#else
sRootNode = std::make_unique<chip::app::RootNode>(rootNodeContext);
#endif
VerifyOrReturnError(sRootNode != nullptr, CHIP_ERROR_NO_MEMORY);
chip::app::ConsecutiveEndpointIdAllocator rootAllocator(kRootEndpointId);
ReturnErrorOnFailure(sRootNode->Register(rootAllocator, *sDataModelProvider));
chip::app::DeviceFactory::GetInstance().Init(chip::app::DeviceFactory::Context{
.groupDataProvider = *groupDataProvider,
.fabricTable = chip::Server::GetInstance().GetFabricTable(),
.timerDelegate = sTimerDelegate,
.storageDelegate = storage,
});
std::string deviceType = chip::app::DeviceFactory::GetInstance().GetDefaultDevice();
char storedDeviceType[64] = {};
uint16_t storedLen = sizeof(storedDeviceType);
CHIP_ERROR storedErr = storage.SyncGetKeyValue(chip::kDeviceTypeKey, storedDeviceType, storedLen);
if (storedErr == CHIP_NO_ERROR && storedLen > 0)
{
deviceType = std::string(storedDeviceType, strnlen(storedDeviceType, storedLen));
}
auto & deviceFactory = chip::app::DeviceFactory::GetInstance();
if (!deviceFactory.IsValidDevice(deviceType))
{
ChipLogError(AppServer, "Invalid device type: %s, falling back to default", deviceType.c_str());
deviceType = deviceFactory.GetDefaultDevice();
}
sConstructedDevice = deviceFactory.Create(deviceType);
VerifyOrReturnError(sConstructedDevice != nullptr, CHIP_ERROR_NO_MEMORY);
ConsecutiveEndpointIdAllocator allocator(kDeviceEndpointId);
ReturnErrorOnFailure(sConstructedDevice->Register(allocator, *sDataModelProvider));
return CHIP_NO_ERROR;
}
chip::app::CodeDrivenDataModelProvider * AppTask::GetDataModelProvider()
{
return sDataModelProvider.get();
}