From c739ab6fcd051c3239ff2a0aa41c25d4dbe3abd5 Mon Sep 17 00:00:00 2001
From: kochalas <konstantinos.chalas@cern.ch>
Date: Fri, 8 Sep 2017 10:50:15 +0200
Subject: [PATCH] [SIL-279] Add support for input and output addressing types
 in the device level

---
 .../interface/core/PLCRecvAction.cpp          | 18 +++---
 .../interface/core/PLCSendAction.cpp          | 20 ++++---
 .../interface/equipment/SilecsDevice.cpp      | 14 +++--
 .../interface/equipment/SilecsDevice.h        | 58 +++++++++++++++++--
 .../interface/equipment/SilecsPLC.cpp         |  8 +--
 5 files changed, 88 insertions(+), 30 deletions(-)

diff --git a/silecs-communication-cpp/src/silecs-communication/interface/core/PLCRecvAction.cpp b/silecs-communication-cpp/src/silecs-communication/interface/core/PLCRecvAction.cpp
index 77e2ca2..9dae94d 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/core/PLCRecvAction.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/core/PLCRecvAction.cpp
@@ -69,9 +69,10 @@ int PLCRecvBlockMode::execute(Context* pContext)
             Device* pDev = pContext->getDevice();
 
             //Base attributes of the device within the complete data block containing all devices.
+            AccessArea area = theBlock_->getAccessArea();
             unsigned long usedAddress = theBlock_->getAddress();
             unsigned long usedSize = theBlock_->getMemSize();
-            unsigned long usedDeviceOffset = pDev->getAddress() * usedSize;
+            unsigned long usedDeviceOffset = pDev->getInputAddress(area) * usedSize;
             unsigned char* pBuffer = ((unsigned char*)theBlock_->getBuffer()) + usedDeviceOffset;
 
             // Overwrite device-block address, offset & size in case user wants to resize the block dynamically
@@ -147,7 +148,8 @@ int PLCRecvBlockMode::execute(Context* pContext)
 
             //begin critical section
             Lock lock(bufferMux_);
-            switch (theBlock_->getAccessArea())
+            AccessArea area = theBlock_->getAccessArea();
+            switch (area)
             {
                 case Digital:
                 case Analog:
@@ -179,7 +181,7 @@ int PLCRecvBlockMode::execute(Context* pContext)
                 for (pDeviceIter = deviceCol.begin(); pDeviceIter != deviceCol.end(); ++pDeviceIter)
                 {
                     Device* pDev = pDeviceIter->second;
-                    unsigned long deviceOffset = pDev->getAddress() * theBlock_->getMemSize();
+                    unsigned long deviceOffset = pDev->getInputAddress(area) * theBlock_->getMemSize();
                     unsigned char* pBuffer = ((unsigned char*)theBlock_->getBuffer()) + deviceOffset;
                     pDev->importRegisters(theBlock_, pBuffer, tod, pContext);
                 }
@@ -212,7 +214,8 @@ int PLCRecvDeviceMode::execute(Context* pContext)
             Device* pDev = pContext->getDevice();
 
             //Set base attributes of the device blocks
-            unsigned long usedDeviceAddress = pDev->getAddress();
+            AccessArea area = theBlock_->getAccessArea();
+            unsigned long usedDeviceAddress = pDev->getInputAddress(area);
             unsigned long usedBlockAddress = theBlock_->getAddress();
             unsigned long usedSize = theBlock_->getMemSize();
 
@@ -294,12 +297,13 @@ int PLCRecvDeviceMode::execute(Context* pContext)
                 }
                 //begin critical section
                 Lock lock(bufferMux_);
-                switch (theBlock_->getAccessArea())
+                AccessArea area = theBlock_->getAccessArea();
+                switch (area)
                 {
                     case Digital:
                     case Analog:
                     {
-                        errorCode = pConn->readIO(theBlock_->getPLC(), pDev->getAddress(), //Base address (or DBn) of the device
+                        errorCode = pConn->readIO(theBlock_->getPLC(), pDev->getInputAddress(area), //Base address (or DBn) of the device
                         theBlock_->getAddress(), //Block data address within the device
                         theBlock_->getMemSize(), //Get one device-block only
                         (unsigned char*)theBlock_->getBuffer() //Buffer to store the data
@@ -309,7 +313,7 @@ int PLCRecvDeviceMode::execute(Context* pContext)
                     case Memory:
                     default:
                     {
-                        errorCode = pConn->readMemory(theBlock_->getPLC(), pDev->getAddress(), //Base address (or DBn) of the device
+                        errorCode = pConn->readMemory(theBlock_->getPLC(), pDev->getInputAddress(area), //Base address (or DBn) of the device
                         theBlock_->getAddress(), //Block data address within the device
                         theBlock_->getMemSize(), //Get one device-block only
                         (unsigned char*)theBlock_->getBuffer() //Buffer to store the data
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/core/PLCSendAction.cpp b/silecs-communication-cpp/src/silecs-communication/interface/core/PLCSendAction.cpp
index 5e96b92..b34efdd 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/core/PLCSendAction.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/core/PLCSendAction.cpp
@@ -70,7 +70,8 @@ int PLCSendBlockMode::execute(Context* pContext)
             //Base attributes of the device within the complete data block containing all devices.
             unsigned long usedAddress = theBlock_->getAddress();
             unsigned long usedSize = theBlock_->getMemSize();
-            unsigned long usedDeviceOffset = pDev->getAddress() * usedSize;
+            AccessArea area = theBlock_->getAccessArea();
+            unsigned long usedDeviceOffset = pDev->getOutputAddress(area) * usedSize;
             unsigned char* pBuffer = ((unsigned char*)theBlock_->getBuffer()) + usedDeviceOffset;
 
             // Overwrite device-block address, offset & size in case user wants to resize the block dynamically
@@ -91,7 +92,7 @@ int PLCSendBlockMode::execute(Context* pContext)
                     pDev->exportRegisters(theBlock_, pBuffer, pContext);
                 }
 
-                switch (theBlock_->getAccessArea())
+                switch (area)
                 {
                     case Digital:
                     case Analog:
@@ -142,7 +143,8 @@ int PLCSendBlockMode::execute(Context* pContext)
                     for (pDeviceIter = deviceCol.begin(); pDeviceIter != deviceCol.end(); ++pDeviceIter)
                     {
                         Device* pDev = pDeviceIter->second;
-                        unsigned long deviceOffset = pDev->getAddress() * theBlock_->getMemSize();
+                        AccessArea area = theBlock_->getAccessArea();
+                        unsigned long deviceOffset = pDev->getOutputAddress(area) * theBlock_->getMemSize();
                         unsigned char* pBuffer = ((unsigned char*)theBlock_->getBuffer()) + deviceOffset;
                         pDev->exportRegisters(theBlock_, pBuffer, pContext);
                     }
@@ -202,7 +204,8 @@ int PLCSendDeviceMode::execute(Context* pContext)
             Device* pDev = pContext->getDevice();
 
             //Set base attributes of the device blocks
-            unsigned long usedDeviceAddress = pDev->getAddress();
+            AccessArea area = theBlock_->getAccessArea();
+            unsigned long usedDeviceAddress = pDev->getOutputAddress(area);
             unsigned long usedBlockAddress = theBlock_->getAddress();
             unsigned long usedSize = theBlock_->getMemSize();
 
@@ -224,7 +227,7 @@ int PLCSendDeviceMode::execute(Context* pContext)
                     pDev->exportRegisters(theBlock_, (unsigned char*)theBlock_->getBuffer(), pContext);
                 }
 
-                switch (theBlock_->getAccessArea())
+                switch (area)
                 {
                     case Digital:
                     case Analog:
@@ -278,12 +281,13 @@ int PLCSendDeviceMode::execute(Context* pContext)
                         pDev->exportRegisters(theBlock_, (unsigned char*)theBlock_->getBuffer(), pContext);
                     }
 
-                    switch (theBlock_->getAccessArea())
+                    AccessArea area = theBlock_->getAccessArea();
+                    switch (area)
                     {
                         case Digital:
                         case Analog:
                         {
-                            errorCode = pConn->writeIO(theBlock_->getPLC(), pDev->getAddress(), //Base address (or DBn) of the device
+                            errorCode = pConn->writeIO(theBlock_->getPLC(), pDev->getOutputAddress(area), //Base address (or DBn) of the device
                             theBlock_->getAddress(), //Block data address within the device
                             theBlock_->getMemSize(), //Set one device-block only
                             (unsigned char*)theBlock_->getBuffer() //Buffer which contain the data
@@ -292,7 +296,7 @@ int PLCSendDeviceMode::execute(Context* pContext)
                         }
                         case Memory:
                         default:
-                            errorCode = pConn->writeMemory(theBlock_->getPLC(), pDev->getAddress(), //Base address (or DBn) of the device
+                            errorCode = pConn->writeMemory(theBlock_->getPLC(), pDev->getOutputAddress(area), //Base address (or DBn) of the device
                             theBlock_->getAddress(), //Block data address within the device
                             theBlock_->getMemSize(), //Set one device-block only
                             (unsigned char*)theBlock_->getBuffer() //Buffer which contain the data
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.cpp
index 1840df0..eb2c96b 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.cpp
@@ -33,13 +33,17 @@
 
 namespace Silecs
 {
-	Device::Device(PLC* thePLC, std::string deviceName, std::string deviceAddress, boost::ptr_vector<ElementXML>& blockNodes) : thePLC_ (thePLC)
+	Device::Device(PLC* thePLC, const ElementXML& deviceNode, boost::ptr_vector<ElementXML>& blockNodes) : thePLC_ (thePLC)
 	{
 		// Update Device ElementXML attributes
-        label_ = deviceName;
-		StringUtilities::fromString(address_,deviceAddress );
-
-        LOG(ALLOC) << "Creating SilecsDevice: " << label_;
+        label_ = deviceNode.getAttribute("label");
+		StringUtilities::fromString(address_,deviceNode.getAttribute("address") );
+		StringUtilities::fromString(ai_address_,deviceNode.getAttribute("AI-address") );
+		StringUtilities::fromString(ao_address_,deviceNode.getAttribute("AO-address") );
+		StringUtilities::fromString(di_address_,deviceNode.getAttribute("DI-address") );
+		StringUtilities::fromString(do_address_,deviceNode.getAttribute("DO-address") );
+
+		LOG(ALLOC) << "Creating SilecsDevice: " << label_;
 
         boost::ptr_vector<ElementXML>::const_iterator blockIter;
         for(blockIter = blockNodes.begin(); blockIter != blockNodes.end(); blockIter++)
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.h b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.h
index 7bd8f97..048b7b2 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.h
@@ -124,10 +124,54 @@ namespace Silecs
         friend class CNVSendBlockMode;
         friend class CNVSendDeviceMode;
 
-		Device(PLC* thePLC, std::string deviceName, std::string deviceAddress, boost::ptr_vector<ElementXML>& blockNodes);
+		Device(PLC* thePLC, const ElementXML& deviceNode, boost::ptr_vector<ElementXML>& blockNodes);
 		virtual ~Device();
 
-		inline unsigned long& getAddress() { return address_; }
+	    inline unsigned long& getInputAddress(AccessArea area)
+	    {
+	        switch (area)
+	        {
+	            case Digital:
+	            {
+	                return di_address_;
+	                break;
+	            }
+	            case Analog:
+	            {
+	                return ai_address_;
+	                break;
+	            }
+	            case Memory:
+	            {
+	                return address_;
+	                break;
+	            }
+	        }
+	        return address_;
+	    }
+
+	    inline unsigned long& getOutputAddress(AccessArea area)
+	    {
+	        switch (area)
+	        {
+	            case Digital:
+	            {
+	                return do_address_;
+	                break;
+	            }
+	            case Analog:
+	            {
+	                return ao_address_;
+	                break;
+	            }
+	            case Memory:
+	            {
+	                return address_;
+	                break;
+	            }
+	        }
+	        return address_;
+	    }
 
 		Register* instantiateRegister(const boost::shared_ptr<ElementXML>& registerNode);
 
@@ -161,9 +205,13 @@ namespace Silecs
 		/// Parent PLC reference of that device
 		PLC* thePLC_;
 
-		/// Device attributes
-		std::string label_;
-		unsigned long address_;
+	    /// Device attributes
+	    std::string label_;
+	    unsigned long address_;
+	    unsigned long ai_address_;
+	    unsigned long ao_address_;
+	    unsigned long di_address_;
+	    unsigned long do_address_;
 
 		/// Register collection of that device
 		registerVectorType registerCol_;
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp
index 9770f08..4996585 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp
@@ -436,11 +436,9 @@ namespace Silecs
 				boost::ptr_vector<ElementXML>::const_iterator instanceIter;
 				for(instanceIter = instanceNodes.begin(); instanceIter != instanceNodes.end(); instanceIter++)
 				{
-					std::string deviceName = (*instanceIter).getAttribute("label");
-					std::string deviceAddress = (*instanceIter).getAttribute("address");
-					Device* pDevice = new Device(this, deviceName, deviceAddress, blockNodes);
-					deviceCol_.push_back(std::make_pair(deviceName, pDevice));
-					if(deviceName == "SilecsHeader")
+					Device* pDevice = new Device(this, *instanceIter, blockNodes);
+					deviceCol_.push_back(std::make_pair(pDevice->getLabel(), pDevice));
+					if(pDevice->getLabel() == "SilecsHeader")
 						theHeader_ = pDevice;
 				}
 
-- 
GitLab