blob: 38eda804acf0b0125ea0e5c270c1773e574e0592 [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 "JFADatastoreSync.h"
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/ConcreteAttributePath.h>
#include <controller/CHIPCluster.h>
#include <lib/support/logging/CHIPLogging.h>
#include <controller/CHIPDeviceController.h>
#include <controller/CommissionerDiscoveryController.h>
using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::Controller;
using namespace chip::app::Clusters::JointFabricDatastore;
extern DeviceCommissioner * GetDeviceCommissioner();
[[maybe_unused]] constexpr uint8_t kJFAvailableShift = 0;
[[maybe_unused]] constexpr uint8_t kJFAdminShift = 1;
[[maybe_unused]] constexpr uint8_t kJFAnchorShift = 2;
[[maybe_unused]] constexpr uint8_t kJFDatastoreShift = 3;
[[maybe_unused]] static constexpr EndpointId kJFDatastoreClusterEndpointId = 1;
JFADatastoreSync JFADatastoreSync::sJFDS;
template <typename T>
class DevicePairedCommand
{
public:
struct CallbackContext
{
NodeId nodeId;
EndpointId endpointId = kRootEndpointId;
T objectToWrite;
std::vector<T> objectsToWrite;
std::function<void()> onSuccess;
std::function<void(CHIP_ERROR, const std::vector<T> &)> onFetchSuccess;
CallbackContext(chip::NodeId nId, T object, std::function<void()> onSuccessFn) :
nodeId(nId), objectToWrite(object), onSuccess(onSuccessFn)
{}
CallbackContext(chip::NodeId nId, std::function<void(CHIP_ERROR, const std::vector<T> &)> onFetchFn) :
nodeId(nId), objectToWrite(), onFetchSuccess(onFetchFn)
{}
CallbackContext(chip::NodeId nId, EndpointId eId, std::function<void(CHIP_ERROR, const std::vector<T> &)> onFetchFn) :
nodeId(nId), endpointId(eId), objectToWrite(), onFetchSuccess(onFetchFn)
{}
CallbackContext(chip::NodeId nId, std::vector<T> objects, std::function<void()> onSuccessFn) :
nodeId(nId), objectsToWrite(objects), onSuccess(onSuccessFn)
{}
};
DevicePairedCommand(
chip::NodeId nodeId, T object, std::function<void()> onSuccess = []() {}) :
mOnDeviceConnectedCallback(OnDeviceConnectedFn, this),
mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
{
mContext = std::make_shared<CallbackContext>(nodeId, object, onSuccess);
}
DevicePairedCommand(
chip::NodeId nodeId, std::function<void(CHIP_ERROR, const std::vector<T> &)> onFetchSuccess = []() {}) :
mOnDeviceConnectedCallback(OnDeviceConnectedFn, this),
mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
{
mContext = std::make_shared<CallbackContext>(nodeId, onFetchSuccess);
mFetchOnly = true;
}
DevicePairedCommand(
chip::NodeId nodeId, EndpointId endpointId,
std::function<void(CHIP_ERROR, const std::vector<T> &)> onFetchSuccess = []() {}) :
mOnDeviceConnectedCallback(OnDeviceConnectedFn, this),
mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
{
mContext = std::make_shared<CallbackContext>(nodeId, endpointId, onFetchSuccess);
mFetchOnly = true;
}
DevicePairedCommand(
chip::NodeId nodeId, std::vector<T> objects, std::function<void()> onSuccess = []() {}) :
mOnDeviceConnectedCallback(OnDeviceConnectedFn, this),
mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
{
mContext = std::make_shared<CallbackContext>(nodeId, objects, onSuccess);
mReplaceExisting = true;
}
static void OnDeviceConnectedFn(void * context, chip::Messaging::ExchangeManager & exchangeMgr,
const chip::SessionHandle & sessionHandle)
{
auto * pairingCommand = static_cast<DevicePairedCommand *>(context);
auto cbContext = pairingCommand->mContext;
CHIP_ERROR err = CHIP_NO_ERROR;
if (pairingCommand)
{
ChipLogProgress(DeviceLayer, "OnDeviceConnectedFn - Syncing device with node id: " ChipLogFormatX64,
ChipLogValueX64(cbContext->nodeId));
if (pairingCommand->mFetchOnly == false)
{
if constexpr (std::is_same_v<
T, app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointGroupIDEntryStruct::Type>)
{
// Invoke Groups:AddGroup on the device's endpoint
chip::app::Clusters::Groups::Commands::AddGroup::Type addGroup;
addGroup.groupID = cbContext->objectToWrite.groupID;
addGroup.groupName = chip::CharSpan::fromCharString("GroupName");
chip::Controller::ClusterBase groupsCluster(exchangeMgr, sessionHandle, cbContext->objectToWrite.endpointID);
err = groupsCluster.InvokeCommand(addGroup, pairingCommand, OnCommandResponse, OnCommandFailure);
}
else if constexpr (std::is_same_v<
T, app::Clusters::JointFabricDatastore::Structs::DatastoreNodeKeySetEntryStruct::Type>)
{
// Invoke GroupKeyManagement::Commands::KeySetWrite on the device
chip::app::Clusters::GroupKeyManagement::Commands::KeySetWrite::Type keySetWrite;
keySetWrite.groupKeySet.groupKeySetID = cbContext->objectToWrite.groupKeySetID;
chip::Controller::ClusterBase groupsCluster(exchangeMgr, sessionHandle, kRootEndpointId);
err = groupsCluster.InvokeCommand(keySetWrite, pairingCommand, OnCommandResponse, OnCommandFailure);
}
else if constexpr (std::is_same_v<
T, app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type>)
{
if (pairingCommand->mReplaceExisting == false)
{
// populate keySetWrite from cbContext->objectToWrite
chip::app::Clusters::Binding::Structs::TargetStruct::Type target;
target.node = cbContext->objectToWrite.binding.node;
target.endpoint = cbContext->objectToWrite.binding.endpoint;
target.cluster = cbContext->objectToWrite.binding.cluster;
target.group = cbContext->objectToWrite.binding.group;
// Create a small array containing the single target and construct a DataModel::List from it
chip::app::Clusters::Binding::Structs::TargetStruct::Type targets[] = { target };
chip::app::Clusters::Binding::Attributes::Binding::TypeInfo::Type keySetWrite =
chip::app::DataModel::List<chip::app::Clusters::Binding::Structs::TargetStruct::Type>(
targets, sizeof(targets) / sizeof(targets[0]));
chip::Controller::ClusterBase groupsCluster(exchangeMgr, sessionHandle,
cbContext->objectToWrite.endpointID);
err = groupsCluster.WriteAttribute<chip::app::Clusters::Binding::Attributes::Binding::TypeInfo>(
keySetWrite, pairingCommand, OnWriteSuccessResponse, OnWriteFailureResponse);
}
else
{
// Create a list of targets from the objectsToWrite vector
std::vector<chip::app::Clusters::Binding::Structs::TargetStruct::Type> targets;
for (const auto & bindingEntry : cbContext->objectsToWrite)
{
chip::app::Clusters::Binding::Structs::TargetStruct::Type target;
target.node = bindingEntry.binding.node;
target.endpoint = bindingEntry.binding.endpoint;
target.cluster = bindingEntry.binding.cluster;
target.group = bindingEntry.binding.group;
targets.push_back(target);
}
chip::app::Clusters::Binding::Attributes::Binding::TypeInfo::Type bindingList =
chip::app::DataModel::List<chip::app::Clusters::Binding::Structs::TargetStruct::Type>(
targets.data(), static_cast<uint32_t>(targets.size()));
chip::Controller::ClusterBase bindingCluster(exchangeMgr, sessionHandle,
cbContext->objectsToWrite[0].endpointID);
err = bindingCluster.WriteAttribute<chip::app::Clusters::Binding::Attributes::Binding::TypeInfo>(
bindingList, pairingCommand, OnWriteSuccessResponse, OnWriteFailureResponse);
}
}
else if constexpr (std::is_same_v<T, app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type>)
{
if (pairingCommand->mReplaceExisting == false)
{
// populate keySetWrite from cbContext->objectToWrite
chip::app::Clusters::AccessControl::Structs::AccessControlEntryStruct::Type target;
target.privilege = static_cast<decltype(target.privilege)>(cbContext->objectToWrite.ACLEntry.privilege);
target.authMode = static_cast<decltype(target.authMode)>(cbContext->objectToWrite.ACLEntry.authMode);
target.subjects = cbContext->objectToWrite.ACLEntry.subjects;
// Convert each DatastoreAccessControlTargetStruct to AccessControl::AccessControlTargetStruct and add to
// list
std::vector<chip::app::Clusters::AccessControl::Structs::AccessControlTargetStruct::Type> convertedTargets;
auto targetsIter = cbContext->objectToWrite.ACLEntry.targets.Value().begin();
auto targetsEnd = cbContext->objectToWrite.ACLEntry.targets.Value().end();
while (targetsIter != targetsEnd)
{
const auto & srcTarget = *targetsIter;
targetsIter++;
chip::app::Clusters::AccessControl::Structs::AccessControlTargetStruct::Type dst{};
dst.cluster = srcTarget.cluster;
dst.endpoint = srcTarget.endpoint;
dst.deviceType = srcTarget.deviceType;
convertedTargets.push_back(dst);
}
target.targets = chip::app::DataModel::List<
const chip::app::Clusters::AccessControl::Structs::AccessControlTargetStruct::Type>(
convertedTargets.data(), static_cast<uint32_t>(convertedTargets.size()));
// Create a small array containing the single target and construct a DataModel::List from it
chip::app::Clusters::AccessControl::Structs::AccessControlEntryStruct::Type targets[] = { target };
chip::app::Clusters::AccessControl::Attributes::Acl::TypeInfo::Type aclList = chip::app::DataModel::List<
const chip::app::Clusters::AccessControl::Structs::AccessControlEntryStruct::Type>(
targets, sizeof(targets) / sizeof(targets[0]));
chip::Controller::ClusterBase groupsCluster(exchangeMgr, sessionHandle, kRootEndpointId);
err = groupsCluster.WriteAttribute<chip::app::Clusters::AccessControl::Attributes::Acl::TypeInfo>(
aclList, pairingCommand, OnWriteSuccessResponse, OnWriteFailureResponse);
}
else
{
// Create a list of ACL entries from the objectsToWrite vector
std::vector<chip::app::Clusters::AccessControl::Structs::AccessControlEntryStruct::Type> aclEntries;
for (const auto & aclEntry : cbContext->objectsToWrite)
{
chip::app::Clusters::AccessControl::Structs::AccessControlEntryStruct::Type entry;
entry.privilege = static_cast<decltype(entry.privilege)>(aclEntry.ACLEntry.privilege);
entry.authMode = static_cast<decltype(entry.authMode)>(aclEntry.ACLEntry.authMode);
entry.subjects = aclEntry.ACLEntry.subjects;
// Convert each DatastoreAccessControlTargetStruct to AccessControl::AccessControlTargetStruct and add
// to list
std::vector<chip::app::Clusters::AccessControl::Structs::AccessControlTargetStruct::Type>
convertedTargets;
auto targetsIter = aclEntry.ACLEntry.targets.Value().begin();
auto targetsEnd = aclEntry.ACLEntry.targets.Value().end();
while (targetsIter != targetsEnd)
{
const auto & srcTarget = *targetsIter;
targetsIter++;
chip::app::Clusters::AccessControl::Structs::AccessControlTargetStruct::Type dst{};
dst.cluster = srcTarget.cluster;
dst.endpoint = srcTarget.endpoint;
dst.deviceType = srcTarget.deviceType;
convertedTargets.push_back(dst);
}
entry.targets = chip::app::DataModel::List<
const chip::app::Clusters::AccessControl::Structs::AccessControlTargetStruct::Type>(
convertedTargets.data(), static_cast<uint32_t>(convertedTargets.size()));
aclEntries.push_back(entry);
}
chip::app::Clusters::AccessControl::Attributes::Acl::TypeInfo::Type aclList = chip::app::DataModel::List<
const chip::app::Clusters::AccessControl::Structs::AccessControlEntryStruct::Type>(
aclEntries.data(), static_cast<uint32_t>(aclEntries.size()));
chip::Controller::ClusterBase accessControlCluster(exchangeMgr, sessionHandle, kRootEndpointId);
err = accessControlCluster.WriteAttribute<chip::app::Clusters::AccessControl::Attributes::Acl::TypeInfo>(
aclList, pairingCommand, OnWriteSuccessResponse, OnWriteFailureResponse);
}
}
else if constexpr (std::is_same_v<T,
app::Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type>)
{
// Invoke GroupKeyManagement::Commands::KeySetWrite on the device
chip::app::Clusters::GroupKeyManagement::Commands::KeySetWrite::Type keySetWrite;
keySetWrite.groupKeySet.groupKeySetID = cbContext->objectToWrite.groupKeySetID;
keySetWrite.groupKeySet.groupKeySecurityPolicy =
static_cast<decltype(keySetWrite.groupKeySet.groupKeySecurityPolicy)>(
cbContext->objectToWrite.groupKeySecurityPolicy);
keySetWrite.groupKeySet.epochKey0 = cbContext->objectToWrite.epochKey0;
keySetWrite.groupKeySet.epochStartTime0 = cbContext->objectToWrite.epochStartTime0;
keySetWrite.groupKeySet.epochKey1 = cbContext->objectToWrite.epochKey1;
keySetWrite.groupKeySet.epochStartTime1 = cbContext->objectToWrite.epochStartTime1;
keySetWrite.groupKeySet.epochKey2 = cbContext->objectToWrite.epochKey2;
keySetWrite.groupKeySet.epochStartTime2 = cbContext->objectToWrite.epochStartTime2;
chip::Controller::ClusterBase groupsCluster(exchangeMgr, sessionHandle, kRootEndpointId);
err = groupsCluster.InvokeCommand(keySetWrite, pairingCommand, OnCommandResponse, OnCommandFailure);
}
else
{
ChipLogError(Controller, "Unknown type for attribute mapping");
return;
}
}
else
{
if constexpr (std::is_same_v<T, app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointEntryStruct::Type>)
{
chip::Controller::ClusterBase descriptorCluster(exchangeMgr, sessionHandle, kRootEndpointId);
err = descriptorCluster.ReadAttribute<chip::app::Clusters::Descriptor::Attributes::PartsList::TypeInfo>(
pairingCommand,
// Success lambda
[](void * lambdaContext,
const chip::app::Clusters::Descriptor::Attributes::PartsList::TypeInfo::DecodableType & dataResponse) {
auto * instance = static_cast<DevicePairedCommand *>(lambdaContext);
auto lambdaCbContext = instance->mContext;
std::vector<T> endpointEntries;
auto iter = dataResponse.begin();
while (iter.Next())
{
auto & responseEntry = iter.GetValue();
T entry;
entry.endpointID = responseEntry;
entry.nodeID = lambdaCbContext->nodeId;
endpointEntries.push_back(entry);
}
if (iter.GetStatus() != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to iterate PartsList: %s", ErrorStr(iter.GetStatus()));
}
if (lambdaCbContext && lambdaCbContext->onFetchSuccess)
{
lambdaCbContext->onFetchSuccess(CHIP_NO_ERROR, endpointEntries);
}
},
// Failure lambda
[](void * lambdaContext, CHIP_ERROR readError) {
auto * instance = static_cast<DevicePairedCommand *>(lambdaContext);
auto lambdaCbContext = instance->mContext;
if (lambdaCbContext && lambdaCbContext->onFetchSuccess)
{
lambdaCbContext->onFetchSuccess(readError, {});
}
});
}
else if constexpr (std::is_same_v<
T, app::Clusters::JointFabricDatastore::Structs::DatastoreGroupInformationEntryStruct::Type>)
{
chip::Controller::ClusterBase groupKeyMgmtCluster(exchangeMgr, sessionHandle,
pairingCommand->mContext->endpointId);
err =
groupKeyMgmtCluster
.ReadAttribute<chip::app::Clusters::GroupKeyManagement::Attributes::GroupKeyMap::TypeInfo>(
pairingCommand,
// Success lambda
[](void * lambdaContext,
const chip::app::Clusters::GroupKeyManagement::Attributes::GroupKeyMap::TypeInfo::DecodableType &
dataResponse) {
auto * instance = static_cast<DevicePairedCommand *>(lambdaContext);
auto lambdaCbContext = instance->mContext;
std::vector<T> groupInfoEntries;
auto iter = dataResponse.begin();
while (iter.Next())
{
auto & responseEntry = iter.GetValue();
T entry;
entry.groupID = responseEntry.groupId;
entry.groupKeySetID = responseEntry.groupKeySetID;
groupInfoEntries.push_back(entry);
}
if (iter.GetStatus() != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to iterate GroupKeyMap: %s", ErrorStr(iter.GetStatus()));
}
if (lambdaCbContext && lambdaCbContext->onFetchSuccess)
{
lambdaCbContext->onFetchSuccess(CHIP_NO_ERROR, groupInfoEntries);
}
},
// Failure lambda
[](void * lambdaContext, CHIP_ERROR readError) {
auto * instance = static_cast<DevicePairedCommand *>(lambdaContext);
auto lambdaCbContext = instance->mContext;
if (lambdaCbContext && lambdaCbContext->onFetchSuccess)
{
lambdaCbContext->onFetchSuccess(readError, {});
}
});
}
else if constexpr (std::is_same_v<
T, app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type>)
{
chip::Controller::ClusterBase bindingCluster(exchangeMgr, sessionHandle, pairingCommand->mContext->endpointId);
err = bindingCluster.ReadAttribute<chip::app::Clusters::Binding::Attributes::Binding::TypeInfo>(
pairingCommand,
// Success lambda
[](void * lambdaContext,
const chip::app::Clusters::Binding::Attributes::Binding::TypeInfo::DecodableType & dataResponse) {
auto * instance = static_cast<DevicePairedCommand *>(lambdaContext);
auto lambdaCbContext = instance->mContext;
std::vector<T> bindingEntries;
auto iter = dataResponse.begin();
while (iter.Next())
{
auto & responseEntry = iter.GetValue();
T entry;
entry.binding.node = responseEntry.node;
entry.binding.endpoint = responseEntry.endpoint;
entry.binding.cluster = responseEntry.cluster;
entry.binding.group = responseEntry.group;
entry.endpointID = lambdaCbContext->objectToWrite.endpointID;
bindingEntries.push_back(entry);
}
if (iter.GetStatus() != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to iterate Binding: %s", ErrorStr(iter.GetStatus()));
}
if (lambdaCbContext && lambdaCbContext->onFetchSuccess)
{
lambdaCbContext->onFetchSuccess(CHIP_NO_ERROR, bindingEntries);
}
},
// Failure lambda
[](void * lambdaContext, CHIP_ERROR readError) {
auto * instance = static_cast<DevicePairedCommand *>(lambdaContext);
auto lambdaCbContext = instance->mContext;
if (lambdaCbContext && lambdaCbContext->onFetchSuccess)
{
lambdaCbContext->onFetchSuccess(readError, {});
}
});
}
else if constexpr (std::is_same_v<T, app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type>)
{
chip::Controller::ClusterBase aclCluster(exchangeMgr, sessionHandle, kRootEndpointId);
err = aclCluster.ReadAttribute<chip::app::Clusters::AccessControl::Attributes::Acl::TypeInfo>(
pairingCommand,
// Success lambda
[](void * lambdaContext,
const chip::app::Clusters::AccessControl::Attributes::Acl::TypeInfo::DecodableType & dataResponse) {
auto * instance = static_cast<DevicePairedCommand *>(lambdaContext);
auto lambdaCbContext = instance->mContext;
std::vector<T> aclEntries;
auto iter = dataResponse.begin();
while (iter.Next())
{
auto & responseEntry = iter.GetValue();
T entry;
entry.ACLEntry.privilege = static_cast<decltype(entry.ACLEntry.privilege)>(responseEntry.privilege);
entry.ACLEntry.authMode = static_cast<decltype(entry.ACLEntry.authMode)>(responseEntry.authMode);
std::vector<uint64_t> subjectsCopy;
auto subjectsIter = responseEntry.subjects.Value().begin();
while (subjectsIter.Next())
{
subjectsCopy.push_back(subjectsIter.GetValue());
}
entry.ACLEntry.subjects = chip::app::DataModel::List<const uint64_t>(
subjectsCopy.data(), static_cast<uint32_t>(subjectsCopy.size()));
std::vector<
chip::app::Clusters::JointFabricDatastore::Structs::DatastoreAccessControlTargetStruct::Type>
convertedTargets;
auto targetsIter = responseEntry.targets.Value().begin();
while (targetsIter.Next())
{
const auto & srcTarget = targetsIter.GetValue();
chip::app::Clusters::JointFabricDatastore::Structs::DatastoreAccessControlTargetStruct::Type
dst{};
dst.cluster = srcTarget.cluster;
dst.endpoint = srcTarget.endpoint;
dst.deviceType = srcTarget.deviceType;
convertedTargets.push_back(dst);
}
entry.ACLEntry.targets =
chip::app::DataModel::List<const chip::app::Clusters::JointFabricDatastore::Structs::
DatastoreAccessControlTargetStruct::Type>(
convertedTargets.data(), static_cast<uint32_t>(convertedTargets.size()));
aclEntries.push_back(entry);
}
if (iter.GetStatus() != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to iterate Acl: %s", ErrorStr(iter.GetStatus()));
}
if (lambdaCbContext && lambdaCbContext->onFetchSuccess)
{
lambdaCbContext->onFetchSuccess(CHIP_NO_ERROR, aclEntries);
}
},
// Failure lambda
[](void * lambdaContext, CHIP_ERROR readError) {
auto * instance = static_cast<DevicePairedCommand *>(lambdaContext);
auto lambdaCbContext = instance->mContext;
if (lambdaCbContext && lambdaCbContext->onFetchSuccess)
{
lambdaCbContext->onFetchSuccess(readError, {});
}
});
}
else
{
ChipLogError(Controller, "Unknown type for attribute mapping");
return;
}
}
if (err != CHIP_NO_ERROR)
{
ChipLogProgress(Controller, "Failed in cluster.WriteAttribute: %s", ErrorStr(err));
}
}
}
static void OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
{
auto * pairingCommand = static_cast<DevicePairedCommand *>(context);
auto cbContext = pairingCommand->mContext;
if (pairingCommand)
{
ChipLogProgress(DeviceLayer, "OnDeviceConnectionFailureFn - Not syncing device with node id: " ChipLogFormatX64,
ChipLogValueX64(cbContext->nodeId));
}
}
/* Callback when command results in success */
static void OnWriteSuccessResponse(void * context)
{
ChipLogProgress(Controller, "OnWriteSuccessResponse - Data written Successfully");
auto * pairingCommand = static_cast<DevicePairedCommand *>(context);
auto cbContext = pairingCommand->mContext;
if (cbContext && cbContext->onSuccess)
{
cbContext->onSuccess();
}
}
/* Callback when command results in failure */
static void OnWriteFailureResponse(void * context, CHIP_ERROR error)
{
ChipLogProgress(Controller, "OnWriteFailureResponse - Failed to write Data: %s", ErrorStr(error));
}
/* Callback when command results in success */
static void OnCommandResponse(void * context,
const chip::app::Clusters::Groups::Commands::AddGroup::Type::ResponseType & response)
{
ChipLogProgress(Controller, "OnCommandResponse - Command executed Successfully");
auto * pairingCommand = static_cast<DevicePairedCommand *>(context);
auto cbContext = pairingCommand->mContext;
if (cbContext && cbContext->onSuccess)
{
cbContext->onSuccess();
}
}
/* Callback when command results in success */
static void
OnCommandResponse(void * context,
const chip::app::Clusters::GroupKeyManagement::Commands::KeySetWrite::Type::ResponseType & response)
{
ChipLogProgress(Controller, "OnCommandResponse - Command executed Successfully");
auto * pairingCommand = static_cast<DevicePairedCommand *>(context);
auto cbContext = pairingCommand->mContext;
if (cbContext && cbContext->onSuccess)
{
cbContext->onSuccess();
}
}
/* Callback when command results in failure */
static void OnCommandFailure(void * context, CHIP_ERROR error)
{
ChipLogProgress(Controller, "OnCommandFailure - Failed to execute Command: %s", ErrorStr(error));
}
chip::Callback::Callback<chip::OnDeviceConnected> mOnDeviceConnectedCallback;
chip::Callback::Callback<chip::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
std::shared_ptr<CallbackContext> mContext;
bool mFetchOnly = false;
bool mReplaceExisting = false;
};
CHIP_ERROR JFADatastoreSync::Init(Server & server)
{
mServer = &server;
return CHIP_NO_ERROR;
}
CHIP_ERROR JFADatastoreSync::SyncNode(
NodeId nodeId,
const app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointGroupIDEntryStruct::Type & endpointGroupIDEntry,
std::function<void()> onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node id: " ChipLogFormatX64, ChipLogValueX64(nodeId));
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointGroupIDEntryStruct::Type>>
pairingCommand = std::make_shared<
DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointGroupIDEntryStruct::Type>>(
nodeId, endpointGroupIDEntry, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR JFADatastoreSync::SyncNode(
NodeId nodeId, const app::Clusters::JointFabricDatastore::Structs::DatastoreNodeKeySetEntryStruct::Type & nodeKeySetEntry,
std::function<void()> onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node id: " ChipLogFormatX64, ChipLogValueX64(nodeId));
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreNodeKeySetEntryStruct::Type>>
pairingCommand = std::make_shared<
DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreNodeKeySetEntryStruct::Type>>(
nodeId, nodeKeySetEntry, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR JFADatastoreSync::SyncNode(
NodeId nodeId, const app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type & bindingEntry,
std::function<void()> onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node id: " ChipLogFormatX64, ChipLogValueX64(nodeId));
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type>>
pairingCommand = std::make_shared<
DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type>>(
nodeId, bindingEntry, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR JFADatastoreSync::SyncNode(
NodeId nodeId,
std::vector<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type> & bindingEntries,
std::function<void()> onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node id: " ChipLogFormatX64, ChipLogValueX64(nodeId));
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type>>
pairingCommand = std::make_shared<
DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type>>(
nodeId, bindingEntries, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR
JFADatastoreSync::SyncNode(NodeId nodeId,
const app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type & aclEntry,
std::function<void()> onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node id: " ChipLogFormatX64, ChipLogValueX64(nodeId));
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type>>
pairingCommand =
std::make_shared<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type>>(
nodeId, aclEntry, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR JFADatastoreSync::SyncNode(
NodeId nodeId, const std::vector<app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type> & aclEntries,
std::function<void()> onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node id: " ChipLogFormatX64, ChipLogValueX64(nodeId));
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type>>
pairingCommand =
std::make_shared<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type>>(
nodeId, aclEntries, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR
JFADatastoreSync::SyncNode(NodeId nodeId,
const app::Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & groupKeySet,
std::function<void()> onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node id: " ChipLogFormatX64, ChipLogValueX64(nodeId));
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type>>
pairingCommand =
std::make_shared<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type>>(
nodeId, groupKeySet, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR JFADatastoreSync::FetchEndpointList(
NodeId nodeId,
std::function<void(
CHIP_ERROR,
const std::vector<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointEntryStruct::Type> & endpointEntryStruct)>
onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node id: " ChipLogFormatX64, ChipLogValueX64(nodeId));
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointEntryStruct::Type>>
pairingCommand =
std::make_shared<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointEntryStruct::Type>>(
nodeId, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR JFADatastoreSync::FetchEndpointGroupList(
NodeId nodeId, EndpointId endpointId,
std::function<void(
CHIP_ERROR, const std::vector<app::Clusters::JointFabricDatastore::Structs::DatastoreGroupInformationEntryStruct::Type> &)>
onSuccess)
{
ChipLogProgress(DeviceLayer, "Fetching group list for node " ChipLogFormatX64 " endpoint %u", ChipLogValueX64(nodeId),
endpointId);
// TODO: Use endpointId to query GetGroupMembership command on that specific endpoint
// For now, create the pairing command with the endpoint parameter
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreGroupInformationEntryStruct::Type>>
pairingCommand = std::make_shared<
DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreGroupInformationEntryStruct::Type>>(
nodeId, endpointId, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR JFADatastoreSync::FetchEndpointBindingList(
NodeId nodeId, EndpointId endpointId,
std::function<void(
CHIP_ERROR, const std::vector<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type> &)>
onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node " ChipLogFormatX64 " endpoint %u", ChipLogValueX64(nodeId),
endpointId);
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type>>
pairingCommand = std::make_shared<
DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type>>(
nodeId, endpointId, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR JFADatastoreSync::FetchGroupKeySetList(
NodeId nodeId,
std::function<void(CHIP_ERROR,
const std::vector<app::Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type> &)>
onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node id: " ChipLogFormatX64, ChipLogValueX64(nodeId));
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type>>
pairingCommand =
std::make_shared<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type>>(
nodeId, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}
CHIP_ERROR JFADatastoreSync::FetchACLList(
NodeId nodeId,
std::function<void(CHIP_ERROR,
const std::vector<app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type> &)>
onSuccess)
{
ChipLogProgress(DeviceLayer, "Creating Pairing Command with node id: " ChipLogFormatX64, ChipLogValueX64(nodeId));
std::shared_ptr<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type>>
pairingCommand =
std::make_shared<DevicePairedCommand<app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type>>(
nodeId, onSuccess);
ReturnErrorOnFailure(GetDeviceCommissioner()->GetConnectedDevice(nodeId, &pairingCommand->mOnDeviceConnectedCallback,
&pairingCommand->mOnDeviceConnectionFailureCallback));
return CHIP_NO_ERROR;
}