From e24e76d7004ebeebc7bea053cf91cd212255867d Mon Sep 17 00:00:00 2001
From: aschwinn <al.schwinn@gsi.de>
Date: Wed, 26 Jul 2017 09:28:21 +0200
Subject: [PATCH] [SIL-279] RIO support: Upgrade the silecs-communication
 library

---
 .../interface/communication/MBConnection.cpp  |  3 ++-
 .../interface/core/SilecsService.h            |  9 ++++++-
 .../interface/equipment/PLCRegister.cpp       |  2 +-
 .../interface/equipment/SilecsBlock.cpp       | 27 +++++++++++++++++++
 .../interface/equipment/SilecsBlock.h         | 14 ++++++++++
 .../interface/equipment/SilecsDevice.cpp      | 10 ++++---
 .../interface/equipment/SilecsDevice.h        |  2 +-
 .../interface/equipment/SilecsPLC.cpp         | 23 +++++++++-------
 .../interface/equipment/SilecsPLC.h           | 23 +++++++++++-----
 .../interface/equipment/SilecsRegister.cpp    | 12 ++++++++-
 .../interface/equipment/SilecsRegister.h      | 27 +++++++++++++++++++
 .../interface/utility/SilecsException.cpp     | 12 ++++++---
 .../interface/utility/SilecsException.h       |  3 ++-
 .../src/silecs-diagnostic/main.cpp            |  1 +
 14 files changed, 139 insertions(+), 29 deletions(-)

diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.cpp b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.cpp
index 6b694e4..e99ee89 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.cpp
@@ -44,7 +44,8 @@ namespace Silecs
         modbus_set_response_timeout(writeCtx_ , &response_timeout);
         */
 
-        //modbus_set_debug(*ctx, TRUE);
+        modbus_set_slave(readCtx_, 1);
+        //modbus_set_debug(readCtx_, TRUE);
 	}
 
 
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/core/SilecsService.h b/silecs-communication-cpp/src/silecs-communication/interface/core/SilecsService.h
index b2efc12..d8eb008 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/core/SilecsService.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/core/SilecsService.h
@@ -33,7 +33,14 @@ namespace Silecs
 	   Input,
 	   InOut
 	} AccessType;
-	/// @endcond READ-ONLY / WRITE-ONLY / READ-WRITE
+
+    // Register and Block access types
+    typedef enum
+    {
+       Memory, Digital, Analog
+    } AccessArea;
+    /// @endcond
+
 
 	/*!
 	 * \brief Defines the category of the SILECS Exception.
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/PLCRegister.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/PLCRegister.cpp
index 7339f5a..69a32c5 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/PLCRegister.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/PLCRegister.cpp
@@ -63,7 +63,7 @@ namespace Silecs
         void *pl = &l;
         void *pul = &ul;
 
-        if ( (getPLC()->getModel() == "BC9020") && (getFormat() == Silecs::Float32) )
+        if ( (getPLC()->getModelID() == BC9xxx) && (getFormat() == Silecs::Float32) )
         {  //Particular case for BC9020 PLC:  swap only bytes together (not the words)
             *((uint16_t *)pul)   = _swaps(*((uint16_t *)pl));
             *((uint16_t *)pul+1) = _swaps(*((uint16_t *)pl+1));
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsBlock.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsBlock.cpp
index 44667bf..292cf26 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsBlock.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsBlock.cpp
@@ -37,6 +37,10 @@ namespace Silecs
 		StringUtilities::fromString(size_,blockNode.getAttribute("size"));
 		StringUtilities::fromString(memSize_,blockNode.getAttribute("mem-size"));
 		StringUtilities::fromString(address_,blockNode.getAttribute("address"));
+		if( blockNode.hasAttribute("ioType") ) // only IO-Blocks have this attribute
+		    accessArea_ = Block::whichAccessArea(blockNode.getAttribute("ioType"));
+		else
+		    accessArea_ = Memory;
 
         resetCustomAttributes(); //by default custom-size of the block is the maximum size
 
@@ -60,6 +64,8 @@ namespace Silecs
 		if (type == "Acquisition-Block") return Input;
 		else if (type == "Command-Block") return Output;
 		else if (type == "Setting-Block") return InOut;
+        else if (type == "Setting-IO-Block") return InOut;
+        else if (type == "Acquisition-IO-Block") return Input;
 		else throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_ACCESS_TYPE, type);
 	}
 
@@ -75,6 +81,27 @@ namespace Silecs
 		}
 	}
 
+    AccessArea Block::whichAccessArea(std::string area)
+    {
+        StringUtilities::toLower(area);
+        if (area == "memory") return Memory;
+        else if (area == "digital-io") return Digital;
+        else if (area == "analog-io") return Analog;
+        else throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_ACCESS_AREA, area);
+    }
+
+
+    std::string Block::whichAccessArea(AccessArea area)
+    {
+        switch(area)
+        {
+        case Memory: return "MEMORY"; break;
+        case Digital: return "DIGITAL-IO"; break;
+        case Analog: return "ANALOG-IO"; break;
+        default: throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_ACCESS_AREA, StringUtilities::toString(area));
+        }
+    }
+
     void Block::setCustomAttributes(const unsigned long customAddress, const unsigned long customOffset, const unsigned long customSize)
     {
         //user wants to limit the size of data to be sent/receive - check that it is lower than design allocation size
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsBlock.h b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsBlock.h
index a0cdfb6..acd015f 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsBlock.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsBlock.h
@@ -49,12 +49,23 @@ namespace Silecs
 		static AccessType whichAccessType(std::string type);
 		static std::string whichAccessType(AccessType type);
 
+        /*!
+         * \fn whichAccessArea
+         * \return the enumeration value of the given access-area string
+         */
+        static AccessArea whichAccessArea(std::string area);
+        static std::string whichAccessArea(AccessArea area);
+
+        inline bool hasInputAccess() { return (accessType_ != Output); }
+        inline bool hasOutputAccess() { return (accessType_ != Input); }
+
 		inline bool isReadable() { return (accessType_ != Output); }
 		inline bool isWritable() { return (accessType_ != Input); }
 
 		inline PLC* getPLC() { return thePLC_; }
 		inline std::string& getName() { return name_; }
 		inline AccessType getAccessType() { return (accessType_); }
+        inline AccessArea getAccessArea() { return (accessArea_); }
 		inline unsigned long& getAddress() { return address_; }
 		inline unsigned long& getMemSize() { return memSize_; }
 		inline Task<WrapperAction>* getTask() { return pTask_; }
@@ -81,6 +92,9 @@ namespace Silecs
 		/// Block access-type: Input, Output or InOut
 		AccessType accessType_;
 
+        /// Block access-type: Memory, Digital or Analog
+        AccessArea accessArea_;
+
 		/// Block size
 		unsigned long size_;
 
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 0888525..1840df0 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.cpp
@@ -47,8 +47,11 @@ namespace Silecs
 			std::string blockName = blockIter->getAttribute("name");
 			LOG(ALLOC) << "Adding Block to Device: " << blockName;
 			AccessType accessType = Block::whichAccessType(blockIter->name_);
+            AccessArea accessArea = Memory;
+	        if( blockIter->hasAttribute("ioType") ) // only IO-Blocks have this attribute
+	            accessArea = Block::whichAccessArea(blockIter->getAttribute("ioType"));
 			std::vector< boost::shared_ptr<ElementXML> > registerNodes = blockIter->childList_;
-			instantiateRegisters(blockName, accessType, registerNodes);
+			instantiateRegisters(blockName, accessType, accessArea, registerNodes);
 		}
 	}
 
@@ -172,7 +175,7 @@ namespace Silecs
 	}
 
 
-	void Device::instantiateRegisters(std::string blockName, AccessType accessType, std::vector< boost::shared_ptr<ElementXML> >& registerNodes)
+	void Device::instantiateRegisters(std::string blockName, AccessType accessType, AccessArea accessArea, std::vector< boost::shared_ptr<ElementXML> >& registerNodes)
 	{
 		std::vector<Register*> registerCol;
 
@@ -183,7 +186,8 @@ namespace Silecs
 		{
 			std::string registerName = (*registerIter)->getAttribute("name");
 			Register* pReg = instantiateRegister(*registerIter);
-			pReg->setAccessType(accessType);
+			pReg->setAccessArea(accessArea);
+            pReg->setAccessType(accessType);
 			pReg->setBlockName(blockName);
 			registerCol.push_back(pReg);
 			registerCol_.push_back(std::make_pair(registerName, pReg));
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 6c100e7..7bd8f97 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsDevice.h
@@ -131,7 +131,7 @@ namespace Silecs
 
 		Register* instantiateRegister(const boost::shared_ptr<ElementXML>& registerNode);
 
-		void instantiateRegisters(std::string blockName, AccessType accessType, std::vector< boost::shared_ptr<ElementXML> >& registerNodes);
+		void instantiateRegisters(std::string blockName, AccessType accessType, AccessArea accessArea, std::vector< boost::shared_ptr<ElementXML> >& registerNodes);
 
 		/*!
          * \fn getBlock
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 0c49b45..b84af33 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp
@@ -126,8 +126,7 @@ namespace Silecs
 			// Thus, even if the PLC is off and rejects the first connection to upload the Header (see updateHeader),
 			// we will automatically attempt to reconnect later at the next PLC accesses (send/recv) ... again and again.
 			plcConn_->enable(this, connectNow);
-
-			if( compareChecksums )
+			if( getTypeID() != BusCoupler && compareChecksums )
 			{
 		        /* PLC memory could have change during a disconnection time (downloading or other).
 		           The Header registers must be reloaded for consistency checking.
@@ -145,7 +144,8 @@ namespace Silecs
 			}
 
             //Warn ACET service that a new connection is established (except for SilecsHeader)
-            if (theHeader_ != NULL) {
+            if (theHeader_ != NULL)
+            {
                 TRACE("info") << "Connection setup: ClassName=" << theCluster_->getClassName() << ", " <<
                                     "ClassVersion=" << theCluster_->getClassVersion() << ", " <<
                                     "Owner=" << localOwner_ << ", " <<
@@ -379,6 +379,7 @@ namespace Silecs
             model_ = mappingNode.getAttribute("plc-model");
             StringUtilities::fromString(baseAddr_,mappingNode.getAttribute("address") );
             usedMem_ = mappingNode.getAttribute("used-mem");
+            typeID_ = whichPLCType(model_);
 			brandID_ = whichPLCBrand(brand_);
             modelID_ = whichPLCModel(model_);
             systemID_ = whichPLCSystem(system_);
@@ -552,9 +553,14 @@ namespace Silecs
 			throw SilecsException(__FILE__, __LINE__, error.str());
 		}
 
-
 		blockVectorType& PLC::getBlockCol() { return blockCol_; }
 
+        PLCType PLC::whichPLCType(std::string model)
+        {
+            StringUtilities::toLower(model);
+            if (model.find("bk9") == 0) return BusCoupler;
+            return BusController;
+        }
 
         PLCBrand PLC::whichPLCBrand(std::string brand)
         {
@@ -580,8 +586,9 @@ namespace Silecs
             else if (model == "premium")            return Premium;
             else if (model == "quantum")            return Quantum;
             else if (model == "m340")               return M340;
-            else if (model == "bc9020")             return BC9020;
-            else if (model == "cx9020")             return CX9020;
+            else if (model.find("bc9") == 0)        return BC9xxx;
+            else if (model.find("cx9") == 0)        return CX9xxx;
+            else if (model.find("bk9") == 0)        return BK9xxx;
             else if (model == "rabbit_rcm_4010")    return RCM4010;
             else if (model == "rabbit_rcm_2000")    return RCM2000;
             else if (model == "compact_rio")        return CompactRIO;
@@ -594,7 +601,7 @@ namespace Silecs
 
         PLCSystem PLC::whichPLCSystem(std::string system)
         {
-            StringUtilities::toLower(system);
+           StringUtilities::toLower(system);
             if (system == "step-7")              return Step7;
             else if (system == "tia-portal")     return TiaPortal;
             else if (system == "snap7 linux32")  return ServerS7;
@@ -606,7 +613,6 @@ namespace Silecs
             else throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_PLC_SYSTEM, system);
         }
 
-
         ProtocolType PLC::whichProtocolType(std::string system)
         {
             StringUtilities::toLower(system);
@@ -621,7 +627,6 @@ namespace Silecs
             else throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_PLC_SYSTEM, system);
         }
 
-
 		ProtocolMode PLC::whichProtocolMode(std::string mode)
 		{
 			StringUtilities::toLower(mode);
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.h b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.h
index 174fbe9..b3387d2 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.h
@@ -36,6 +36,12 @@ namespace Silecs
 	typedef std::vector<Block*> blockVectorType;
     typedef std::map<std::string, Connection*> connMapType;
 
+    // PLC type, brand, system, protocol type and mode
+    typedef enum
+    {
+       BusController, BusCoupler
+    } PLCType;
+
 	// PLC brand, system, protocol type and mode
     typedef enum
     {
@@ -46,9 +52,8 @@ namespace Silecs
     {
         ET200S, S7300, S7400, S71200, S71500,
         S7VIRTUAL,
-        Premium, Quantum,
-        M340,
-        BC9020, CX9020,
+        Premium, Quantum, M340,
+        BC9xxx, CX9xxx, BK9xxx,
         RCM4010, RCM2000,
         CompactRIO,
         PXIRT, PXIWindows, PCWindows, OtherSupportCNV
@@ -367,6 +372,7 @@ namespace Silecs
 		friend class InputBlock;
 		friend class OutputBlock;
 		friend class PLCRegister;
+        friend class TwinCATRegister;
 		friend class PLCRecvBlockMode;
 		friend class PLCRecvDeviceMode;
 		friend class PLCSendBlockMode;
@@ -385,6 +391,7 @@ namespace Silecs
 		PLC(Cluster* theCluster, std::string plcName, std::string plcIPaddr, string parameterFile = "");
 		virtual ~PLC();
 
+        inline PLCType& getTypeID() { return typeID_; }
 		inline PLCBrand& getBrandID() { return brandID_; }
         inline PLCModel& getModelID() { return modelID_; }
         inline PLCSystem& getSystemID() { return systemID_; }
@@ -424,6 +431,7 @@ namespace Silecs
          * \fn whichPLC, whichProtocol...
          * \return the enumeration value of the given Protocol type/mode string
          */
+        static PLCType whichPLCType(std::string model);   //BusController, BusCoupler
 		static PLCBrand whichPLCBrand(std::string brand); //SIEMENS, SCHNEIDER, BECKHOFF, ...
         static PLCModel whichPLCModel(std::string model); //S7-400, S7-300, ...
         static PLCSystem whichPLCSystem(std::string system); //STEP-7, UNITY, TWINCAT, ...
@@ -460,13 +468,14 @@ namespace Silecs
 		/// PLC attributes
 		std::string name_;
 		std::string IPaddr_;
-		std::string domain_; //TST, ADE, PSB, CPS, ..
-		std::string brand_; //SIEMENS, SCHNEIDER, ..
-        std::string system_; //STEP-7, UNITY, TWINCAT, ..
-		std::string model_; //SIMATIC S7-300, Premium, ..
+        std::string domain_;  //TST, ADE, PSB, CPS, ..
+        std::string brand_;   //SIEMENS, SCHNEIDER, ..
+        std::string system_;  //STEP-7, UNITY, TWINCAT, ..
+        std::string model_;   //SIMATIC S7-300, Premium, ..
 		std::string protocolMode_; //Device, Block
 		std::string protocolType_; //MODBUS-TCP, S7-TCP, ..
 		
+        PLCType typeID_;   //BusController (with CPU), BusCoupler (pure IO)
 		PLCBrand brandID_; //Siemens, Schneider, ... enumeration
         PLCModel modelID_; //S7-400, S7-300, ... enumeration
         PLCSystem systemID_; //Step7, Unity, TwinCat, ... enumeration
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp
index 5b4bf90..3929c08 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp
@@ -383,6 +383,12 @@ namespace Silecs
 	double* Register::getRefFloat64Array2D(uint32_t& dim1, uint32_t& dim2) { return getRefArray2D<double>(Float64, dim1, dim2); }
 
 	// SET methods =============================================================
+
+    void Register::setAccessArea(AccessArea accessArea)
+    {
+        accessArea_ = accessArea;
+    }
+
 	void Register::setAccessType(AccessType accessType)
 	{
 	  accessType_ =  accessType;
@@ -637,10 +643,11 @@ namespace Silecs
 
 	// .........................................................................
 	std::string Register::getName() { return name_; }
+    AccessArea Register::getAccessArea() { return accessArea_; }
 	unsigned long Register::getDimension(uint16_t whichDim) { return ((whichDim == 2) ? dimension2_ : dimension1_); }
 	uint32_t Register::getDimension1() { return dimension1_; }
 	uint32_t Register::getDimension2() { return dimension2_; }
-	uint32_t Register::getLength() {return length_; };
+	uint32_t Register::getLength() {return length_; }
 	FormatType Register::getFormat() { return format_; }
 	std::string Register::getBlockName() { return blockName_; }
 	std::string Register::getFormatAsString() { return FormatTypeString[format_]; }
@@ -648,6 +655,9 @@ namespace Silecs
 	bool Register::isReadable() { return (accessType_ != Output); }
 	bool Register::isWritable() { return (accessType_ != Input); }
 
+    bool Register::isIORegister() { return (accessArea_ != Memory); }
+    bool Register::isMemoryRegister() { return (accessArea_ == Memory); }
+
 	bool Register::isVolatile(){ return isVolatile_; }
     bool Register::isScalar() { return ((dimension1_ == 1) && (dimension2_ == 1)); }
     bool Register::isSingleArray() { return ((dimension1_ > 1) && (dimension2_ == 1)); }
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.h b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.h
index c730b4d..da18094 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.h
@@ -107,6 +107,12 @@ namespace Silecs
          */
 		std::string getName();
 
+        /*!
+        * \brief Returns the register access area (same as the related block as defined in the Class design)
+        * \return Register area: Memory, Digital, Analog
+        */
+       AccessArea getAccessArea();
+
         /*!
          * \brief Returns the format of the register data
          * \return value from the FormatType enumeration
@@ -150,6 +156,18 @@ namespace Silecs
 
 		bool isWritable();
 
+        /*!
+         * \brief A register can be Memory or IO peripheral register.
+         * \return true if the register is an IO register (Digital, Analog)
+         */
+        bool isIORegister();
+
+        /*!
+         * \brief A register can be Memory or IO peripheral register.
+         * \return true if the register is a Memory register
+         */
+        bool isMemoryRegister();
+
         /*!
          * \brief A register that has not persistent or constant value is Volatile.
          * Its value is not initialized at the system start-up.
@@ -1594,6 +1612,12 @@ namespace Silecs
          */
 		void setAccessType(AccessType accessType);
 
+        /*!
+         * \brief Set access area.
+         * \param accessArea Memory, Digital or Analog
+         */
+        void setAccessArea(AccessArea accessArea);
+
 		inline void setBlockName(const std::string blockName) { blockName_ = blockName; }
 
         /*!
@@ -1652,6 +1676,9 @@ namespace Silecs
 		/// Register access-type: Input, Ouput or InOut (following its related block)
 		AccessType accessType_;
 
+        /// Register access-area: Memory, Digital or Analog (following its related block)
+        AccessArea accessArea_;
+
 		/// Enum format: char, uchar, short, ushort, long, ulong, float, double
 		FormatType format_;
 
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/utility/SilecsException.cpp b/silecs-communication-cpp/src/silecs-communication/interface/utility/SilecsException.cpp
index 8274e22..82d0508 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/utility/SilecsException.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/utility/SilecsException.cpp
@@ -143,10 +143,14 @@ namespace Silecs
 				errCategory_ = DATA_FAULT;
 				errMessage_ = "Register Design has a wrong data format: ";
 				break;
-			case DATA_UNKNOWN_ACCESS_TYPE:
-				errCategory_ = DATA_FAULT;
-				errMessage_ = "Block Design has a wrong access-type: ";
-				break;
+            case DATA_UNKNOWN_ACCESS_TYPE:
+                errCategory_ = DATA_FAULT;
+                errMessage_ = "Block Design has a wrong access type: ";
+                break;
+            case DATA_UNKNOWN_ACCESS_AREA:
+                errCategory_ = DATA_FAULT;
+                errMessage_ = "Block Design has a wrong access area: ";
+                break;
 			case DATA_UNKNOWN_PLC_MANUFACTURER:
 				errCategory_ = DATA_FAULT;
 				errMessage_ = "Controller Deployment has a wrong manufacturer: ";
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/utility/SilecsException.h b/silecs-communication-cpp/src/silecs-communication/interface/utility/SilecsException.h
index 1cc455c..5aaaa65 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/utility/SilecsException.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/utility/SilecsException.h
@@ -94,7 +94,8 @@ namespace Silecs
         DIAG_PLC_REPORT_NOT_SUPPORTED,
 		CNV_INTERNAL_ERROR,
 		UNEXPECTED_ERROR,
-		UNKNOWN_ERROR
+        UNKNOWN_ERROR,
+        DATA_UNKNOWN_ACCESS_AREA
 	} ErrorCode;
 
 	/*!
diff --git a/silecs-diagnostic-cpp/src/silecs-diagnostic/main.cpp b/silecs-diagnostic-cpp/src/silecs-diagnostic/main.cpp
index f9b9106..036ade5 100755
--- a/silecs-diagnostic-cpp/src/silecs-diagnostic/main.cpp
+++ b/silecs-diagnostic-cpp/src/silecs-diagnostic/main.cpp
@@ -19,6 +19,7 @@
 #include <silecs-diagnostic/diagnostictoolmainview.h>
 #include <silecs-diagnostic/loginhandler.h>
 #include <silecs-diagnostic/silecsmodule.h>
+#include <silecs-communication/interface/utility/XMLParser.h>
 
 
 silecsModule *mysilecs;
-- 
GitLab