blob: bb457daf2c6ac1b001b42971d9f854c29357e253 [file] [log] [blame]
/*
*
* 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.
*/
/**
* @file
* Generic trait data sinks.
*/
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#include <stdint.h>
#include <inttypes.h>
// Note that the choice of namespace alias must be made up front for each and every compile unit
// This is because many include paths could set the default alias to unintended target.
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <time.h>
#include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h>
#include <Weave/Core/WeaveCore.h>
#include <Weave/Support/Base64.h>
#include <Weave/Support/CodeUtils.h>
#include <Weave/Core/WeaveEncoding.h>
#include <Weave/Profiles/WeaveProfiles.h>
#include <Weave/Profiles/common/CommonProfile.h>
#include <Weave/Profiles/echo/WeaveEcho.h>
#include <Weave/Profiles/network-provisioning/NetworkProvisioning.h>
#include <Weave/Profiles/service-provisioning/ServiceProvisioning.h>
#include <Weave/Profiles/fabric-provisioning/FabricProvisioning.h>
#include <Weave/Profiles/data-management/DataManagement.h>
#include <Weave/Profiles/device-description/DeviceDescription.h>
#include <Weave/Profiles/device-control/DeviceControl.h>
#include <Weave/Profiles/vendor/nestlabs/device-description/NestProductIdentifiers.hpp>
#include <Weave/Profiles/security/WeaveSecurity.h>
#include <Weave/Profiles/security/WeaveAccessToken.h>
#include <Weave/Profiles/token-pairing/TokenPairing.h>
#include <Weave/DeviceManager/WeaveDeviceManager.h>
#include <Weave/Support/verhoeff/Verhoeff.h>
#include <Weave/Support/crypto/WeaveCrypto.h>
#include <Weave/Support/logging/WeaveLogging.h>
#include <Weave/Support/ErrorStr.h>
#include <Weave/Support/NestCerts.h>
#include <Weave/Support/TimeUtils.h>
#include <Weave/Profiles/vendor/nestlabs/dropcam-legacy-pairing/DropcamLegacyPairing.h>
#include <Weave/Support/CodeUtils.h>
#include <Weave/DeviceManager/WeaveDataManagementClient.h>
#include <Weave/DeviceManager/TraitSchemaDirectory.h>
namespace nl {
namespace Weave {
namespace DeviceManager {
using namespace nl::Weave::Encoding;
using namespace nl::Weave::Profiles;
using namespace nl::Weave::Profiles::DataManagement;
using namespace nl::Weave::Profiles::DeviceDescription;
using namespace nl::Weave::Profiles::Security;
using namespace nl::Weave::Profiles::ServiceProvisioning;
using namespace ::nl::Weave;
using namespace ::nl::Weave::TLV;
using namespace Schema::Weave::Common;
class GenericTraitDataSink;
class WDMClient;
GenericTraitDataSink::GenericTraitDataSink(const nl::Weave::Profiles::DataManagement::TraitSchemaEngine * aEngine)
: TraitUpdatableDataSink(aEngine)
{
}
GenericTraitDataSink::~GenericTraitDataSink()
{
Close();
}
void GenericTraitDataSink::Close(void)
{
for (auto itr = mPathTlvDataMap.begin(); itr != mPathTlvDataMap.end(); ++itr)
{
if (NULL != itr->second)
{
PacketBuffer::Free(itr->second);
mPathTlvDataMap.erase(itr->first);
}
}
}
void GenericTraitDataSink::UpdateTLVDataMap(PropertyPathHandle aPropertyPathHandle, PacketBuffer *apMsgBuf)
{
if ((mPathTlvDataMap.find(aPropertyPathHandle) != mPathTlvDataMap.end()) && (NULL != mPathTlvDataMap[aPropertyPathHandle]))
{
PacketBuffer::Free(mPathTlvDataMap[aPropertyPathHandle]);
}
mPathTlvDataMap[aPropertyPathHandle] = apMsgBuf;
}
WEAVE_ERROR GenericTraitDataSink::LocateTraitHandle(void* appReqState, const TraitCatalogBase<TraitDataSink> * const apCatalog, TraitDataHandle & aHandle)
{
GenericTraitDataSink * pGenericTraitDataSink = static_cast<GenericTraitDataSink *>(appReqState);
return apCatalog->Locate(pGenericTraitDataSink, aHandle);
}
WEAVE_ERROR GenericTraitDataSink::RefreshData(WDMClient* apWDMClient, WDMClientCompleteFunct onComplete, WDMClientErrorFunct onError)
{
return apWDMClient->RefreshData(this, onComplete, onError, LocateTraitHandle);
}
WEAVE_ERROR GenericTraitDataSink::SetData(const char * apPath, int8_t aValue, bool aIsConditional)
{
return Set(apPath, aValue, aIsConditional);
}
WEAVE_ERROR GenericTraitDataSink::SetData(const char * apPath, int16_t aValue, bool aIsConditional)
{
return Set(apPath, aValue, aIsConditional);
}
WEAVE_ERROR GenericTraitDataSink::SetData(const char * apPath, int32_t aValue, bool aIsConditional)
{
return Set(apPath, aValue, aIsConditional);
}
WEAVE_ERROR GenericTraitDataSink::SetData(const char * apPath, int64_t aValue, bool aIsConditional)
{
return Set(apPath, aValue, aIsConditional);
}
WEAVE_ERROR GenericTraitDataSink::SetData(const char * apPath, uint8_t aValue, bool aIsConditional)
{
return Set(apPath, aValue, aIsConditional);
}
WEAVE_ERROR GenericTraitDataSink::SetData(const char * apPath, uint16_t aValue, bool aIsConditional)
{
return Set(apPath, aValue, aIsConditional);
}
WEAVE_ERROR GenericTraitDataSink::SetData(const char * apPath, uint32_t aValue, bool aIsConditional)
{
return Set(apPath, aValue, aIsConditional);
}
WEAVE_ERROR GenericTraitDataSink::SetData(const char * apPath, uint64_t aValue, bool aIsConditional)
{
return Set(apPath, aValue, aIsConditional);
}
WEAVE_ERROR GenericTraitDataSink::SetData(const char * apPath, double aValue, bool aIsConditional)
{
return Set(apPath, aValue, aIsConditional);
}
WEAVE_ERROR GenericTraitDataSink::SetBoolean(const char * apPath, bool aValue, bool aIsConditional)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVWriter writer;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;
PacketBuffer *pMsgBuf = PacketBuffer::New();
VerifyOrExit(NULL != pMsgBuf, err = WEAVE_ERROR_NO_MEMORY);
VerifyOrExit(GetSubscriptionClient() != NULL, err = WEAVE_ERROR_INCORRECT_STATE);
Lock(GetSubscriptionClient());
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
writer.Init(pMsgBuf);
err = writer.PutBoolean(AnonymousTag, aValue);
SuccessOrExit(err);
err = writer.Finalize();
SuccessOrExit(err);
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
UpdateTLVDataMap(propertyPathHandle, pMsgBuf);
pMsgBuf = NULL;
err = SetUpdated(GetSubscriptionClient(), propertyPathHandle, aIsConditional);
Unlock(GetSubscriptionClient());
WeaveLogDetail(DataManagement, "<set updated> in 0x%08x", propertyPathHandle);
exit:
WeaveLogFunctError(err);
if (NULL != pMsgBuf)
{
PacketBuffer::Free(pMsgBuf);
pMsgBuf = NULL;
}
return err;
}
WEAVE_ERROR GenericTraitDataSink::SetString(const char * apPath, const char * aValue, bool aIsConditional)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVWriter writer;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;
PacketBuffer *pMsgBuf = PacketBuffer::New();
VerifyOrExit(NULL != pMsgBuf, err = WEAVE_ERROR_NO_MEMORY);
VerifyOrExit(GetSubscriptionClient() != NULL, err = WEAVE_ERROR_INCORRECT_STATE);
Lock(GetSubscriptionClient());
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
writer.Init(pMsgBuf);
err = writer.PutString(AnonymousTag, aValue);
SuccessOrExit(err);
err = writer.Finalize();
SuccessOrExit(err);
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
UpdateTLVDataMap(propertyPathHandle, pMsgBuf);
pMsgBuf = NULL;
err = SetUpdated(GetSubscriptionClient(), propertyPathHandle, aIsConditional);
Unlock(GetSubscriptionClient());
WeaveLogDetail(DataManagement, "<set updated> in 0x%08x", propertyPathHandle);
exit:
WeaveLogFunctError(err);
if (NULL != pMsgBuf)
{
PacketBuffer::Free(pMsgBuf);
pMsgBuf = NULL;
}
return err;
}
WEAVE_ERROR GenericTraitDataSink::SetNull(const char * apPath, bool aIsConditional)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVWriter writer;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;
PacketBuffer *pMsgBuf = PacketBuffer::New();
VerifyOrExit(NULL != pMsgBuf, err = WEAVE_ERROR_NO_MEMORY);
VerifyOrExit(GetSubscriptionClient() != NULL, err = WEAVE_ERROR_INCORRECT_STATE);
Lock(GetSubscriptionClient());
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
writer.Init(pMsgBuf);
err = writer.PutNull(AnonymousTag);
SuccessOrExit(err);
err = writer.Finalize();
SuccessOrExit(err);
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
UpdateTLVDataMap(propertyPathHandle, pMsgBuf);
pMsgBuf = NULL;
err = SetUpdated(GetSubscriptionClient(), propertyPathHandle, aIsConditional);
Unlock(GetSubscriptionClient());
WeaveLogDetail(DataManagement, "<set updated> in 0x%08x", propertyPathHandle);
exit:
WeaveLogFunctError(err);
if (NULL != pMsgBuf)
{
PacketBuffer::Free(pMsgBuf);
pMsgBuf = NULL;
}
return err;
}
WEAVE_ERROR GenericTraitDataSink::SetLeafBytes(const char * apPath, const uint8_t * dataBuf, size_t dataLen, bool aIsConditional)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVWriter writer;
nl::Weave::TLV::TLVReader reader;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;
PacketBuffer *pMsgBuf = PacketBuffer::New();
VerifyOrExit(NULL != pMsgBuf, err = WEAVE_ERROR_NO_MEMORY);
VerifyOrExit(GetSubscriptionClient() != NULL, err = WEAVE_ERROR_INCORRECT_STATE);
Lock(GetSubscriptionClient());
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
writer.Init(pMsgBuf);
reader.Init(dataBuf, dataLen);
reader.Next();
writer.CopyElement(AnonymousTag, reader);
err = writer.Finalize();
SuccessOrExit(err);
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
UpdateTLVDataMap(propertyPathHandle, pMsgBuf);
pMsgBuf = NULL;
err = SetUpdated(GetSubscriptionClient(), propertyPathHandle, aIsConditional);
Unlock(GetSubscriptionClient());
WeaveLogDetail(DataManagement, "<set updated> in 0x%08x", propertyPathHandle);
exit:
WeaveLogFunctError(err);
if (NULL != pMsgBuf)
{
PacketBuffer::Free(pMsgBuf);
pMsgBuf = NULL;
}
return err;
}
WEAVE_ERROR GenericTraitDataSink::SetBytes(const char * apPath, const uint8_t * dataBuf, size_t dataLen, bool aIsConditional)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
TLVReader reader;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;
VerifyOrExit(GetSubscriptionClient() != NULL, err = WEAVE_ERROR_INCORRECT_STATE);
Lock(GetSubscriptionClient());
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
reader.Init(dataBuf, dataLen);
err = reader.Next();
SuccessOrExit(err);
err = StoreDataElement(propertyPathHandle, reader, 0, NULL, NULL);
SuccessOrExit(err);
err = SetUpdated(GetSubscriptionClient(), propertyPathHandle, aIsConditional);
Unlock(GetSubscriptionClient());
WeaveLogDetail(DataManagement, "<set updated> in 0x%08x", propertyPathHandle);
exit:
WeaveLogFunctError(err);
return err;
}
template <class T>
WEAVE_ERROR GenericTraitDataSink::Set(const char * apPath, T aValue, bool aIsConditional)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVWriter writer;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;
PacketBuffer *pMsgBuf = PacketBuffer::New();
VerifyOrExit(NULL != pMsgBuf, err = WEAVE_ERROR_NO_MEMORY);
VerifyOrExit(GetSubscriptionClient() != NULL, err = WEAVE_ERROR_INCORRECT_STATE);
Lock(GetSubscriptionClient());
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
writer.Init(pMsgBuf);
err = writer.Put(AnonymousTag, aValue);
SuccessOrExit(err);
err = writer.Finalize();
SuccessOrExit(err);
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
UpdateTLVDataMap(propertyPathHandle, pMsgBuf);
pMsgBuf = NULL;
err = SetUpdated(GetSubscriptionClient(), propertyPathHandle, aIsConditional);
Unlock(GetSubscriptionClient());
WeaveLogDetail(DataManagement, "<set updated> in 0x%08x", propertyPathHandle);
exit:
WeaveLogFunctError(err);
if (NULL != pMsgBuf)
{
PacketBuffer::Free(pMsgBuf);
pMsgBuf = NULL;
}
return err;
}
WEAVE_ERROR GenericTraitDataSink::GetData(const char * apPath, int8_t& aValue)
{
return Get(apPath, aValue);
}
WEAVE_ERROR GenericTraitDataSink::GetData(const char * apPath, int16_t& aValue)
{
return Get(apPath, aValue);
}
WEAVE_ERROR GenericTraitDataSink::GetData(const char * apPath, int32_t& aValue)
{
return Get(apPath, aValue);
}
WEAVE_ERROR GenericTraitDataSink::GetData(const char * apPath, int64_t& aValue)
{
return Get(apPath, aValue);
}
WEAVE_ERROR GenericTraitDataSink::GetData(const char * apPath, uint8_t& aValue)
{
return Get(apPath, aValue);
}
WEAVE_ERROR GenericTraitDataSink::GetData(const char * apPath, uint16_t& aValue)
{
return Get(apPath, aValue);
}
WEAVE_ERROR GenericTraitDataSink::GetData(const char * apPath, uint32_t& aValue)
{
return Get(apPath, aValue);
}
WEAVE_ERROR GenericTraitDataSink::GetData(const char * apPath, uint64_t& aValue)
{
return Get(apPath, aValue);
}
WEAVE_ERROR GenericTraitDataSink::GetData(const char * apPath, double& aValue)
{
return Get(apPath, aValue);
}
WEAVE_ERROR GenericTraitDataSink::GetBoolean(const char * apPath, bool& aValue)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVReader reader;
PacketBuffer *pMsgBuf = NULL;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;;
std::map<PropertyPathHandle, PacketBuffer *>::iterator it;
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
it = mPathTlvDataMap.find(propertyPathHandle);
VerifyOrExit(it != mPathTlvDataMap.end(), err = WEAVE_ERROR_INCORRECT_STATE);
pMsgBuf = mPathTlvDataMap[propertyPathHandle];
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
reader.Init(pMsgBuf);
err = reader.Next();
SuccessOrExit(err);
err = reader.Get(aValue);
SuccessOrExit(err);
exit:
WeaveLogFunctError(err);
return err;
}
WEAVE_ERROR GenericTraitDataSink::GetString(const char * apPath, char * aValue)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVReader reader;
PacketBuffer *pMsgBuf = NULL;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;;
std::map<PropertyPathHandle, PacketBuffer *>::iterator it;
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
it = mPathTlvDataMap.find(propertyPathHandle);
VerifyOrExit(it != mPathTlvDataMap.end(), err = WEAVE_ERROR_INCORRECT_STATE);
pMsgBuf = mPathTlvDataMap[propertyPathHandle];
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
reader.Init(pMsgBuf);
err = reader.Next();
SuccessOrExit(err);
err = reader.GetString(aValue, sizeof(aValue));
SuccessOrExit(err);
exit:
WeaveLogFunctError(err);
return err;
}
WEAVE_ERROR GenericTraitDataSink::GetLeafBytes(const char * apPath, ConstructBytesArrayFunct aCallback)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVReader reader;
PacketBuffer *pMsgBuf = NULL;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;;
std::map<PropertyPathHandle, PacketBuffer *>::iterator it;
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
it = mPathTlvDataMap.find(propertyPathHandle);
VerifyOrExit(it != mPathTlvDataMap.end(), err = WEAVE_ERROR_INCORRECT_STATE);
pMsgBuf = mPathTlvDataMap[propertyPathHandle];
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
aCallback(pMsgBuf->Start(), pMsgBuf->DataLength());
exit:
WeaveLogFunctError(err);
return err;
}
WEAVE_ERROR GenericTraitDataSink::GetBytes(const char * apPath, ConstructBytesArrayFunct aCallback)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
TraitSchemaEngine::IGetDataDelegate *getDataDelegate;
TLVType dummyContainerType;
nl::Weave::TLV::TLVWriter writer;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;
PacketBuffer *pMsgBuf = PacketBuffer::New();
VerifyOrExit(NULL != pMsgBuf, err = WEAVE_ERROR_NO_MEMORY);
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
writer.Init(pMsgBuf);
err = writer.StartContainer(AnonymousTag, kTLVType_Structure, dummyContainerType);
SuccessOrExit(err);
getDataDelegate = static_cast<TraitSchemaEngine::IGetDataDelegate *>(this);
err = GetSchemaEngine()->RetrieveData(propertyPathHandle, ContextTag(DataElement::kCsTag_Data), writer, getDataDelegate);
SuccessOrExit(err);
err = writer.EndContainer(dummyContainerType);
SuccessOrExit(err);
err = writer.Finalize();
SuccessOrExit(err);
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
aCallback(pMsgBuf->Start(), pMsgBuf->DataLength());
exit:
WeaveLogFunctError(err);
if (NULL != pMsgBuf)
{
PacketBuffer::Free(pMsgBuf);
pMsgBuf = NULL;
}
return err;
}
WEAVE_ERROR GenericTraitDataSink::IsNull(const char * apPath, bool & aIsNull)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVReader reader;
PacketBuffer *pMsgBuf = NULL;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;;
std::map<PropertyPathHandle, PacketBuffer *>::iterator it;
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
it = mPathTlvDataMap.find(propertyPathHandle);
VerifyOrExit(it != mPathTlvDataMap.end(), err = WEAVE_ERROR_INCORRECT_STATE);
pMsgBuf = mPathTlvDataMap[propertyPathHandle];
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
reader.Init(pMsgBuf);
err = reader.Next();
SuccessOrExit(err);
if (reader.GetType() == kTLVElementType_Null)
{
aIsNull = true;
}
else {
aIsNull = false;
}
exit:
WeaveLogFunctError(err);
return err;
}
template <class T>
WEAVE_ERROR GenericTraitDataSink::Get(const char * apPath, T &aValue)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVReader reader;
PacketBuffer *pMsgBuf = NULL;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;
std::map<PropertyPathHandle, PacketBuffer *>::iterator it;
err = GetSchemaEngine()->MapPathToHandle(apPath, propertyPathHandle);
SuccessOrExit(err);
it = mPathTlvDataMap.find(propertyPathHandle);
VerifyOrExit(it != mPathTlvDataMap.end(), err = WEAVE_ERROR_INCORRECT_STATE);
pMsgBuf = mPathTlvDataMap[propertyPathHandle];
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
reader.Init(pMsgBuf);
err = reader.Next();
SuccessOrExit(err);
err = reader.Get(aValue);
SuccessOrExit(err);
exit:
WeaveLogFunctError(err);
return err;
}
WEAVE_ERROR
GenericTraitDataSink::SetLeafData(PropertyPathHandle aLeafHandle, TLVReader &aReader)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVWriter writer;
PacketBuffer *pMsgBuf = PacketBuffer::New();
VerifyOrExit(NULL != pMsgBuf, err = WEAVE_ERROR_NO_MEMORY);
writer.Init(pMsgBuf);
err = writer.CopyElement(AnonymousTag, aReader);
SuccessOrExit(err);
err = writer.Finalize();
SuccessOrExit(err);
UpdateTLVDataMap(aLeafHandle, pMsgBuf);
pMsgBuf = NULL;
exit:
WeaveLogFunctError(err);
if (NULL != pMsgBuf)
{
PacketBuffer::Free(pMsgBuf);
pMsgBuf = NULL;
}
return err;
}
WEAVE_ERROR
GenericTraitDataSink::GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, TLVWriter &aWriter)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVReader reader;
PacketBuffer *pMsgBuf = NULL;
std::map<PropertyPathHandle, PacketBuffer *>::iterator it = mPathTlvDataMap.find(aLeafHandle);
VerifyOrExit(it != mPathTlvDataMap.end(), err = WEAVE_ERROR_INCORRECT_STATE);
pMsgBuf = mPathTlvDataMap[aLeafHandle];
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
err = DebugPrettyPrint(pMsgBuf);
SuccessOrExit(err);
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
reader.Init(pMsgBuf);
err = reader.Next();
SuccessOrExit(err);
err = aWriter.CopyElement(aTagToWrite, reader);
SuccessOrExit(err);
exit:
WeaveLogFunctError(err);
return err;
}
WEAVE_ERROR GenericTraitDataSink::GetNextDictionaryItemKey(PropertyPathHandle aDictionaryHandle, uintptr_t &aContext, PropertyDictionaryKey &aKey)
{
return WEAVE_END_OF_INPUT;
}
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
void GenericTraitDataSink::TLVPrettyPrinter(const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
vprintf(aFormat, args);
va_end(args);
}
WEAVE_ERROR GenericTraitDataSink::DebugPrettyPrint(PacketBuffer *apMsgBuf)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
nl::Weave::TLV::TLVReader reader;
reader.Init(apMsgBuf);
err = reader.Next();
SuccessOrExit(err);
nl::Weave::TLV::Debug::Dump(reader, TLVPrettyPrinter);
exit:
if (WEAVE_NO_ERROR != err)
{
WeaveLogProgress(DataManagement, "DebugPrettyPrint fails with err %d", err);
}
return err;
}
#endif //WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
const nl::Weave::ExchangeContext::Timeout kResponseTimeoutMsec = 15000;
WDMClient::WDMClient() :
mpPublisherPathList(NULL),
mpSubscriptionClient(NULL),
mpMsgLayer(NULL),
mAppReqState(NULL)
{
mOpState = kOpState_Idle;
}
WDMClient::~WDMClient(void)
{
Close();
}
void WDMClient::Close(void)
{
//if (NULL == mpBinding)
//{
// mpBinding->Release();
// mpBinding = NULL;
//}
mSinkCatalog.Clear();
if (mpPublisherPathList != NULL)
{
delete[] mpPublisherPathList;
}
if (mpSubscriptionClient != NULL)
{
mpSubscriptionClient->Free();
mpSubscriptionClient = NULL;
}
mpMsgLayer = NULL;
mAppReqState = NULL;
mOpState = kOpState_Idle;
}
void WDMClient::ClientEventCallback (void * const aAppState, SubscriptionClient::EventID aEvent,
const SubscriptionClient::InEventParam & aInParam, SubscriptionClient::OutEventParam & aOutParam)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
WDMClient * const pWDMDMClient = reinterpret_cast<WDMClient *>(aAppState);
OpState savedOpState = pWDMDMClient->mOpState;
WeaveLogDetail(DataManagement, "WDM ClientEventCallback: current op is, %d", savedOpState);
switch (aEvent)
{
case SubscriptionClient::kEvent_OnExchangeStart:
WeaveLogDetail(DataManagement, "Client->kEvent_OnExchangeStart");
break;
case SubscriptionClient::kEvent_OnSubscribeRequestPrepareNeeded:
WeaveLogDetail(DataManagement, "Client->kEvent_OnSubscribeRequestPrepareNeeded");
{
uint16_t pathListLen = 0;
uint16_t traitListLen = 0;
TraitDataHandle handle;
bool NeedSubscribeAll = true;
if (pWDMDMClient->mGetDataHandle != NULL && pWDMDMClient->mAppReqState != NULL)
{
traitListLen = 1;
err = pWDMDMClient->mGetDataHandle(pWDMDMClient->mAppReqState, &pWDMDMClient->mSinkCatalog, handle);
SuccessOrExit(err);
NeedSubscribeAll = false;
}
else
{
NeedSubscribeAll = true;
traitListLen = pWDMDMClient->mSinkCatalog.Count();
}
if (pWDMDMClient->mpPublisherPathList == NULL)
{
pWDMDMClient->mpPublisherPathList = new TraitPath[traitListLen];
}
else
{
delete[] pWDMDMClient->mpPublisherPathList;
pWDMDMClient->mpPublisherPathList = new TraitPath[traitListLen];
}
pWDMDMClient->mSinkCatalog.PrepareSubscriptionPathList(pWDMDMClient->mpPublisherPathList,
traitListLen,
pathListLen, handle, NeedSubscribeAll);
aOutParam.mSubscribeRequestPrepareNeeded.mPathList = pWDMDMClient->mpPublisherPathList;
aOutParam.mSubscribeRequestPrepareNeeded.mPathListSize = pathListLen;
aOutParam.mSubscribeRequestPrepareNeeded.mNeedAllEvents = false;
aOutParam.mSubscribeRequestPrepareNeeded.mLastObservedEventList = NULL;
aOutParam.mSubscribeRequestPrepareNeeded.mLastObservedEventListSize = 0;
aOutParam.mSubscribeRequestPrepareNeeded.mTimeoutSecMin = 30;
aOutParam.mSubscribeRequestPrepareNeeded.mTimeoutSecMax = 3600;
}
break;
case SubscriptionClient::kEvent_OnSubscriptionEstablished:
WeaveLogDetail(DataManagement, "Client->kEvent_OnSubscriptionEstablished");
pWDMDMClient->mpSubscriptionClient->AbortSubscription();
VerifyOrExit(kOpState_RefreshData == pWDMDMClient->mOpState, err = WEAVE_ERROR_INCORRECT_STATE);
pWDMDMClient->ClearOpState();
pWDMDMClient->mOnComplete.General(pWDMDMClient, pWDMDMClient->mAppReqState);
break;
case SubscriptionClient::kEvent_OnNotificationRequest:
WeaveLogDetail(DataManagement, "Client->kEvent_OnNotificationRequest");
break;
case SubscriptionClient::kEvent_OnNotificationProcessed:
WeaveLogDetail(DataManagement, "Client->kEvent_OnNotificationProcessed");
break;
case SubscriptionClient::kEvent_OnSubscriptionTerminated:
WeaveLogDetail(DataManagement, "Client->kEvent_OnSubscriptionTerminated. Reason: %u, peer = 0x%" PRIX64 "\n",
aInParam.mSubscriptionTerminated.mReason,
aInParam.mSubscriptionTerminated.mClient->GetPeerNodeId());
pWDMDMClient->mpSubscriptionClient->AbortSubscription();
err = WEAVE_ERROR_INCORRECT_STATE;
break;
case SubscriptionClient::kEvent_OnUpdateComplete:
if ((aInParam.mUpdateComplete.mReason == WEAVE_NO_ERROR) && (nl::Weave::Profiles::kWeaveProfile_Common == aInParam.mUpdateComplete.mStatusProfileId) && (nl::Weave::Profiles::Common::kStatus_Success == aInParam.mUpdateComplete.mStatusCode))
{
WeaveLogDetail(DataManagement, "Update: path result: success");
}
else
{
TraitDataSink *sink = NULL;
WeaveLogDetail(DataManagement, "Update: path failed: %s, %s, tdh %" PRIu16", will %sretry",
ErrorStr(aInParam.mUpdateComplete.mReason),
nl::StatusReportStr(aInParam.mUpdateComplete.mStatusProfileId, aInParam.mUpdateComplete.mStatusCode),
aInParam.mUpdateComplete.mTraitDataHandle,
aInParam.mUpdateComplete.mWillRetry ? "" : "not ");
WeaveLogDetail(DataManagement, "discard failed change");
pWDMDMClient->mSinkCatalog.Locate(aInParam.mUpdateComplete.mTraitDataHandle, &sink);
pWDMDMClient->mpSubscriptionClient->DiscardUpdates();
}
VerifyOrExit(kOpState_FlushUpdate == pWDMDMClient->mOpState, err = WEAVE_ERROR_INCORRECT_STATE);
pWDMDMClient->ClearOpState();
pWDMDMClient->mOnComplete.General(pWDMDMClient, pWDMDMClient->mAppReqState);
break;
case SubscriptionClient::kEvent_OnNoMorePendingUpdates:
WeaveLogDetail(DataManagement, "Update: no more pending updates");
break;
default:
SubscriptionClient::DefaultEventHandler(aEvent, aInParam, aOutParam);
break;
}
exit:
if (WEAVE_NO_ERROR != err)
{
pWDMDMClient->ClearOpState();
WeaveLogError(DataManagement, "WDM ClientEventCallback failure: err = %d", err);
pWDMDMClient->mOnError(pWDMDMClient, pWDMDMClient->mAppReqState, err, NULL);
}
return;
}
WEAVE_ERROR WDMClient::Init( WeaveMessageLayer * apMsgLayer, Binding * apBinding)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
mpMsgLayer = apMsgLayer;
if (mpSubscriptionClient == NULL)
{
err = SubscriptionEngine::GetInstance()->NewClient(&mpSubscriptionClient,
apBinding,
this,
ClientEventCallback,
&mSinkCatalog,
kResponseTimeoutMsec * 2); // max num of msec between subscribe request and subscribe response
SuccessOrExit(err);
}
mpSubscriptionClient->EnableResubscribe(NULL);
exit:
return WEAVE_NO_ERROR;
}
WEAVE_ERROR WDMClient::NewDataSink(const ResourceIdentifier & aResourceId, uint32_t aProfileId, uint64_t aInstanceId, const char * apPath, GenericTraitDataSink *& apGenericTraitDataSink)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
PropertyPathHandle handle = kNullPropertyPathHandle;
VerifyOrExit(WEAVE_NO_ERROR != GetDataSink(aResourceId, aProfileId, aInstanceId, apGenericTraitDataSink), WeaveLogDetail(DataManagement, "Trait (profile id: %" PRIu32", instance id): % exist", aProfileId, aInstanceId));
apGenericTraitDataSink = new GenericTraitDataSink(TraitSchemaDirectory::GetTraitSchemaEngine(aProfileId));
VerifyOrExit(apGenericTraitDataSink != NULL, err = WEAVE_ERROR_NO_MEMORY);
if (apPath == NULL)
{
handle = kRootPropertyPathHandle;
}
else
{
apGenericTraitDataSink->GetSchemaEngine()->MapPathToHandle(apPath, handle);
}
err = SubscribePublisherTrait(aResourceId, aInstanceId, handle, apGenericTraitDataSink);
SuccessOrExit(err);
apGenericTraitDataSink->SetSubscriptionClient(mpSubscriptionClient);
//WeaveLogProgress(DataManagement, "%s", __PRETTY_FUNCTION__);
exit:
return err;
}
WEAVE_ERROR WDMClient::GetDataSink(const ResourceIdentifier & aResourceId, uint32_t aProfileId, uint64_t aInstanceId, GenericTraitDataSink *& apGenericTraitDataSink)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
TraitDataSink * dataSink = NULL;
err = mSinkCatalog.Locate(aProfileId, aInstanceId, aResourceId, &dataSink);
SuccessOrExit(err);
apGenericTraitDataSink = static_cast<GenericTraitDataSink *>(dataSink);
exit:
return err;
}
WEAVE_ERROR WDMClient::FlushUpdate(void* appReqState, WDMClientCompleteFunct onComplete, WDMClientErrorFunct onError)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
VerifyOrExit(mOpState == kOpState_Idle, err = WEAVE_ERROR_INCORRECT_STATE);
mAppReqState = appReqState;
mOnComplete.General = onComplete;
mOnError = onError;
mOpState = kOpState_FlushUpdate;
err = mpSubscriptionClient->FlushUpdate();
SuccessOrExit(err);
exit:
if (err != WEAVE_NO_ERROR)
{
ClearOpState();
}
return err;
}
WEAVE_ERROR WDMClient::RefreshData(void* appReqState, WDMClientCompleteFunct onComplete, WDMClientErrorFunct onError, GetDataHandleFunct getDataHandleCb)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
VerifyOrExit(mOpState == kOpState_Idle, err = WEAVE_ERROR_INCORRECT_STATE);
mAppReqState = appReqState;
mOnComplete.General = onComplete;
mOnError = onError;
mOpState = kOpState_RefreshData;
mGetDataHandle = getDataHandleCb;
mpSubscriptionClient->InitiateSubscription();
exit:
if (err != WEAVE_NO_ERROR)
{
ClearOpState();
}
return err;
}
void WDMClient::ClearOpState()
{
mOpState = kOpState_Idle;
}
WEAVE_ERROR WDMClient::SubscribePublisherTrait(const ResourceIdentifier & aResourceId, const uint64_t & aInstanceId,
PropertyPathHandle aBasePathHandle, TraitDataSink * apDataSink)
{
TraitDataHandle traitHandle;
return mSinkCatalog.Add(aResourceId, aInstanceId, aBasePathHandle, apDataSink, traitHandle);
}
WEAVE_ERROR WDMClient::UnsubscribePublisherTrait(TraitDataSink * apDataSink)
{
return mSinkCatalog.Remove(apDataSink);
}
} // namespace DeviceManager
} // namespace Weave
} // namespace nl
namespace nl {
namespace Weave {
namespace Profiles {
namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) {
SubscriptionEngine * SubscriptionEngine::GetInstance()
{
static nl::Weave::Profiles::DataManagement::SubscriptionEngine gWdmSubscriptionEngine;
return &gWdmSubscriptionEngine;
}
namespace Platform {
void CriticalSectionEnter()
{
return;
}
void CriticalSectionExit()
{
return;
}
} // Platform
} // WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current)
} // Profiles
} // Weave
} // nl