Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions modules/opcua_client_module/src/opcua_client_module_impl.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
#include <opcua_client_module/opcua_client_module_impl.h>
#include <opcua_client_module/version.h>
#include <coretypes/version_info_factory.h>
#include <chrono>
#include <opcuatms_client/tms_client.h>
#include <opendaq/custom_log.h>
#include <coretypes/version_info_factory.h>
#include <coreobjects/property_object_factory.h>
#include <coreobjects/property_factory.h>
#include <opendaq/custom_log.h>
#include <opendaq/device_type_factory.h>
#include <opendaq/mirrored_signal_config_ptr.h>
#include <opendaq/search_filter_factory.h>
#include <regex>
#include <opendaq/address_info_factory.h>
#include <coreobjects/property_factory.h>

#include <opendaq/mirrored_device_config_ptr.h>
#include <opendaq/device_private_ptr.h>
#include <regex>

BEGIN_NAMESPACE_OPENDAQ_OPCUA_CLIENT_MODULE
static const char* DaqOpcUaDeviceTypeId = "OpenDAQOPCUAConfiguration";
Expand Down Expand Up @@ -115,6 +114,7 @@ DevicePtr OpcUaClientModule::onCreateDevice(const StringPtr& connectionString,
.addAddressInfo(addressInfo)
.freeze();

device.asPtr<IDevicePrivate>(true).setAsRoot();
return device;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class TmsClientComponentBaseImpl : public TmsClientPropertyObjectBaseImpl<Impl>

// Component overrides
ErrCode INTERFACE_FUNC getActive(Bool* active) override;
ErrCode INTERFACE_FUNC getLocalActive(Bool* active) override;
ErrCode INTERFACE_FUNC getParentActive(Bool* active) override;
ErrCode INTERFACE_FUNC setActive(Bool active) override;
ErrCode INTERFACE_FUNC getName(IString** name) override;
ErrCode INTERFACE_FUNC setName(IString* name) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class TmsClientDeviceImpl : public TmsClientComponentBaseImpl<MirroredDeviceBase
ErrCode INTERFACE_FUNC setOperationMode(OperationModeType modeType) override;
ErrCode INTERFACE_FUNC setOperationModeRecursive(OperationModeType modeType) override;
ErrCode INTERFACE_FUNC getOperationMode(OperationModeType* modeType) override;
ErrCode INTERFACE_FUNC getParentActive(Bool* active) override;

protected:
void findAndCreateSubdevices();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ ErrCode TmsClientComponentBaseImpl<Impl>::getActive(Bool* active)
return OPENDAQ_SUCCESS;
}

template <class Impl>
ErrCode TmsClientComponentBaseImpl<Impl>::getLocalActive(Bool* active)
{
return DAQ_MAKE_ERROR_INFO(OPENDAQ_ERR_NOT_SUPPORTED);
}

template <class Impl>
ErrCode TmsClientComponentBaseImpl<Impl>::getParentActive(Bool* active)
{
ComponentPtr parent;
OPENDAQ_RETURN_IF_FAILED(this->getParent(&parent));

if (parent.assigned())
return parent->getActive(active);
else
*active = True;
return OPENDAQ_SUCCESS;
}

template <class Impl>
ErrCode TmsClientComponentBaseImpl<Impl>::setActive(Bool active)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,19 @@ PropertyObjectPtr TmsClientDeviceImpl::onCreateDefaultAddDeviceConfig()
return PropertyObject();
}

ErrCode TmsClientDeviceImpl::getParentActive(Bool* active)
{
OPENDAQ_PARAM_NOT_NULL(active);

if (this->isRootDevice)
{
*active = True;
return OPENDAQ_SUCCESS;
}

return Super::getParentActive(active);
}

void TmsClientDeviceImpl::findAndCreateFunctionBlocks()
{
std::map<uint32_t, FunctionBlockPtr> orderedFunctionBlocks;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,95 @@ TEST_F(TmsFolderTest, Active)
folder.clientFolder.getItems()[0].asPtr<IFolder>().getItems()[0].getActive());
}

TEST_F(TmsFolderTest, GetParentActiveParentIsActive)
{
auto folder = registerTestFolder(createTestFolder());

auto child = folder.clientFolder.getItems()[0];
Bool active = false;
ASSERT_EQ(child->getParentActive(&active), OPENDAQ_SUCCESS);
ASSERT_EQ(active, folder.serverFolder.getActive());
}

TEST_F(TmsFolderTest, GetParentActiveParentIsInactive)
{
auto folder = registerTestFolder(createTestFolder());

folder.clientFolder.setActive(false);
auto child = folder.clientFolder.getItems()[0];
Bool active = true;
ASSERT_EQ(child->getParentActive(&active), OPENDAQ_SUCCESS);
ASSERT_EQ(active, folder.serverFolder.getActive());
}

// When the folder is set inactive, nested components inherit that state:
// server's getActive() returns localActive && parentActive, so OPC UA
// reflects the combined value. All assertions below verify client == server.

TEST_F(TmsFolderTest, NestedActiveInheritsParentInactive)
{
auto folder = registerTestFolder(createTestFolder());
auto child = folder.clientFolder.getItems()[0];

// baseline
ASSERT_TRUE(folder.clientFolder.getActive());
ASSERT_TRUE(child.getActive());

folder.clientFolder.setActive(false);

ASSERT_FALSE(folder.clientFolder.getActive());
ASSERT_EQ(folder.serverFolder.getActive(), folder.clientFolder.getActive());

// child's getActive reads OPC UA which reflects parentActive && localActive
ASSERT_FALSE(child.getActive());
ASSERT_EQ(folder.serverFolder.getItems()[0].getActive(), child.getActive());
}

TEST_F(TmsFolderTest, NestedGetParentActiveMatchesFolderActive)
{
auto folder = registerTestFolder(createTestFolder());
auto child = folder.clientFolder.getItems()[0];

folder.clientFolder.setActive(false);

Bool parentActive;
ASSERT_EQ(child->getParentActive(&parentActive), OPENDAQ_SUCCESS);
ASSERT_FALSE(parentActive);
ASSERT_EQ(parentActive, folder.serverFolder.getActive());
}

TEST_F(TmsFolderTest, DeepNestedActiveInheritsParentInactive)
{
auto folder = registerTestFolder(createTestFolder());
auto child = folder.clientFolder.getItems()[0];
auto leaf = child.asPtr<IFolder>().getItems()[0];

folder.clientFolder.setActive(false);

// leaf.getActive() reads OPC UA: serverLeaf.getActive() = localActive && serverChild.getActive()
// = true && (localActive && serverFolder.getActive()) = true && (true && false) = false
ASSERT_FALSE(leaf.getActive());
ASSERT_EQ(folder.serverFolder.getItems()[0].asPtr<IFolder>().getItems()[0].getActive(), leaf.getActive());

// leaf.getParentActive() calls child.getActive() which is also false
Bool parentActive;
ASSERT_EQ(leaf->getParentActive(&parentActive), OPENDAQ_SUCCESS);
ASSERT_FALSE(parentActive);
}

TEST_F(TmsFolderTest, NestedActiveRestoresAfterFolderReactivated)
{
auto folder = registerTestFolder(createTestFolder());
auto child = folder.clientFolder.getItems()[0];

folder.clientFolder.setActive(false);
ASSERT_FALSE(child.getActive());

folder.clientFolder.setActive(true);
ASSERT_TRUE(child.getActive());
ASSERT_EQ(folder.serverFolder.getItems()[0].getActive(), child.getActive());
}

TEST_F(TmsFolderTest, Tags)
{
auto folder = registerTestFolder(createTestFolder());
Expand Down
Loading