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 e99ee8988ea0592a57a1a26bb6db4f7d0401226b..ccceca4bafe1849e9d57b06140f22063ad016bec 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.cpp
@@ -21,6 +21,10 @@
 #include <silecs-communication/interface/utility/SilecsException.h>
 #include <silecs-communication/protocol/modbus/iemdb.h>
 
+//Modbus max data size definition (byte counting)
+#define MAX_WRITE_DATA_SIZE MODBUS_MAX_WRITE_REGISTERS*2
+#define MAX_READ_DATA_SIZE  MODBUS_MAX_READ_REGISTERS*2
+
 namespace Silecs
 {
 
@@ -98,7 +102,7 @@ namespace Silecs
 			//DATA topic makes sense with RECV one
 			if (RECV & Log::topics_) LOG(DATA) << "Read data, address: %MW" << addr << ", byte-size: " << size;
 
-            int err = IeMBreadData(readCtx_, addr, (unsigned short)size, pBuffer);
+            int err = mbReadData(readCtx_, addr, (unsigned short)size, pBuffer);
 	        if(error)
 	        	throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," ModBus Error: " + string(IeGetErrorMessage(error)));
 		}
@@ -131,12 +135,72 @@ namespace Silecs
 			//DATA topic makes sense with SEND one
 			if (SEND & Log::topics_) LOG(DATA) << "Write data, address: %MW" << addr << ", byte-size: " << size;
 
-			int error = IeMBwriteData(writeCtx_, (unsigned short)addr, (unsigned short)size, pBuffer);
+			int error = mbWriteData(writeCtx_, (unsigned short)addr, (unsigned short)size, pBuffer);
 	        if(error)
 	        	throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," ModBus Error: " + string(IeGetErrorMessage(error)));
 		}
 		return 0;
 	}
 
+	  /*----------------------------------------------------------*/
+	  int MBConnection::mbWriteData(modbus_t* ctx, uint16_t start_addr, uint16_t count, uint8_t* data)
+	  {
+	      uint16_t *srcp = (uint16_t*)data;
+	      int word_count, byte_count;
+
+	      while(count)
+	      {
+	          word_count = (count > MAX_WRITE_DATA_SIZE) ? MAX_WRITE_DATA_SIZE/2 : (count/2)+(count%2);
+	          byte_count = (word_count * 2);
+
+	          if (modbus_write_registers(ctx, start_addr, word_count, srcp) != word_count)
+	          {
+	              return errno;
+	          }
+
+	          //srcp += byte_count-(count%2);
+	          srcp += word_count;
+	          start_addr += word_count;
+	          count -= (byte_count - (count%2));
+	      }
+
+	      return 0;
+	  }
+
+	  /*----------------------------------------------------------*/
+	  int MBConnection::mbReadData(modbus_t* ctx, uint16_t start_addr, uint16_t count, uint8_t* data)
+	  {
+	    uint16_t *destp = (uint16_t*)data;
+	    int word_count, byte_count;
+
+	    while(count) {
+
+	        if (count > MAX_READ_DATA_SIZE)
+	        {
+	           /*'word_count' is a word counter*/
+	           word_count = MAX_READ_DATA_SIZE/2;
+	        }
+	        else
+	        {
+	          /*'word_count' is a word counter*/
+	          word_count = (count/2) + (count%2);
+	        }
+
+	        byte_count = (word_count * 2);
+
+	        if (modbus_read_registers(ctx, start_addr, word_count, destp) != word_count)
+	        {
+	            return errno;
+	        }
+
+	        //destp += (byte_count-(count%2));
+	        destp += word_count;
+	        start_addr += word_count;
+	        count -= (byte_count - (count%2));
+	    }
+
+	    return 0;
+	  }
+
 } // namespace
 #endif //MODBUS_SUPPORT_ENABLED
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.h
index fd67d2db413243cee4117f8ec89c12f5dc7a9936..0cfc8de1fd3000af914ac843785b7623ccd5ffe1 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBConnection.h
@@ -42,6 +42,9 @@ namespace Silecs
         modbus_t* writeCtx_;
 		bool open(PLC* thePLC);
 		bool close(PLC* thePLC);
+	    int mbWriteData(modbus_t* ctx, uint16_t dataAddr, uint16_t dataSize, uint8_t* dataBuffer);
+	    int mbReadData(modbus_t* ctx, uint16_t dataAddr, uint16_t dataSize, uint8_t* dataBuffer);
+	    bool checkError(PLC* thePLC, int err, bool retry);
 
 	};
 
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBHardware.cpp b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBHardware.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..35a51cf8283f238ce77c6e6a6416434b38821b97
--- /dev/null
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBHardware.cpp
@@ -0,0 +1,98 @@
+// Copyright 2016 CERN and GSI
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#ifdef MODBUS_SUPPORT_ENABLED
+#include "MBHardware.h"
+
+/*----------------------------------------------------------*/
+/* Time funtion
+ * IeMdbSetTime: Convert lynxos time_t format to PLC SCHNEIDER
+ * format.
+ *
+ * Details:
+ * PLC SCHNEIER format is coded on 8 bytes BCD
+ * format:
+ *
+ *  0      1      2      3      4      5     6     7
+ *  SC     00     HH     MN     MM     DD    YY    YY
+ *
+ *  byte 1 is used by gateway to synchronize time setting.
+ */
+void IeMdbSetTime(unsigned char *dt, time_t epoch)  // to PLC
+{
+  struct tm *dscst;
+  dscst = localtime(&epoch);
+
+  /*v1.7*/
+  /*In fact, each 16bits word is swapped with SCHNEIDER PLC
+    1      0      3      2      5      4     7     6
+    SC     00     HH     MN     MM     DD    YY    YY
+
+    Swapping can do it directly during data transferring
+  */
+
+  dt[1] = _tobcd(dscst->tm_sec);
+  dt[0] = 0x00; /*not used*/
+  dt[3] = _tobcd(dscst->tm_hour);
+  dt[2] = _tobcd(dscst->tm_min);
+  dt[5] = _tobcd(dscst->tm_mon+1);
+  dt[4] = _tobcd(dscst->tm_mday);
+  dt[7] = _tobcd(2000/100);
+  dt[6] = _tobcd(dscst->tm_year-100);
+}
+
+/*----------------------------------------------------------*/
+/* Time funtion
+ * IeMdbGetTime: Convert PLC SCHNEIDER format to time_t format.
+ *
+ * Details:
+ * PLC SCHNEIER format is coded on 8 bytes BCD
+ * format:
+ *
+ *  0      1        2      3      4      5     6     7
+ *  SC     SC/100   HH     MN     MM     DD    YY    YY
+ *
+ */
+double IeMdbGetTime(unsigned char *dt) // from PLC
+{
+  struct tm plcst;
+  time_t plctm;
+  double ms;
+  int year;
+
+  /*In fact, each 16bits word is swapped with SCHNEIDER PLC
+    1      0        3      2      5      4     7     6
+    SC     SC/100   HH     MN     MM     DD    YY    YY
+
+    Swapping can do it directly during data transferring
+  */
+
+  plcst.tm_sec  = _frombcd(dt[1]);
+  plcst.tm_hour = _frombcd(dt[3]);
+  plcst.tm_min  = _frombcd(dt[2]);
+  plcst.tm_mon  = _frombcd(dt[5])-1;
+  plcst.tm_mday = _frombcd(dt[4]);
+  year = _frombcd(dt[6]);
+  //look at Schneider DATA_AND_TIME type documentation
+  plcst.tm_year = ((year >= 90) ? year : year+100);
+  /*plcst.tm_wday = no used in PLC*/
+  /*plcst.tm_yday = no used in PLC*/
+
+  ms = ((double)_frombcd(dt[0])/100.);
+  plcst.tm_isdst = -1; // daylight saving time unavailable
+  plctm = mktime(&plcst);
+
+  return((double)plctm + ms);
+}
+#endif //MODBUS_SUPPORT_ENABLED
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/MBHardware.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBHardware.h
new file mode 100644
index 0000000000000000000000000000000000000000..c436c29f784da54177421450997625e4a3610b17
--- /dev/null
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/MBHardware.h
@@ -0,0 +1,54 @@
+// Copyright 2016 CERN and GSI
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#ifdef MODBUS_SUPPORT_ENABLED
+#ifndef _MBHARDWARE_H_
+#define _MBHARDWARE_H_
+
+#include <silecs-communication/protocol/core/ietype.h>
+#include <modbus.h>
+
+/*----------------------------------------------------------*/
+/* Time funtion
+ * IeMdbSetTime: Convert time_t epoch date to PLC SCHNEIDER
+ * format.
+ *
+ * Details:
+ * PLC SCHNEIER format is coded on 8 bytes BCD
+ * format:
+ *
+ *  0      1      2      3      4      5     6     7
+ *  SC     --     HH     MN     MM     DD    YY    YY
+ *
+ *  byte 1 is used by gateway to synchronize time setting.
+ */
+void IeMdbSetTime(unsigned char *dt, time_t epoch);  // to PLC
+
+/*----------------------------------------------------------*/
+/* Time funtion
+ * IeMdbGetTime: Convert PLC SCHNEIDER format to lynxOS
+ * time_t format.
+ *
+ * Details:
+ * PLC SCHNEIER format is coded on 8 bytes BCD
+ * format:
+ *
+ *  0      1        2      3      4      5     6     7
+ *  SC     SC/100   HH     MN     MM     DD    YY    YY
+ *
+ */
+double IeMdbGetTime(unsigned char *dt); // from PLC
+
+#endif /* _MBHARDWARE_H_ */
+#endif //MODBUS_SUPPORT_ENABLED
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.cpp b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.cpp
index 861afc40eb9e061b024875274e17385d9ca1a987..02859a615c71b92b8135d179e44e17d4e3bf7976 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.cpp
@@ -25,238 +25,267 @@
 namespace Silecs
 {
 
-	SNAP7Connection::SNAP7Connection(PLC* thePLC) : Connection(thePLC)
-	{
-        rackNb_ = 0;    //rackNb - common rack is 0 so far
-        slotNb_ = -1;   //slotNb - depends on hardware configuration (scan is required the first connect)
-
-		recvClient_ = Cli_Create();
-        sendClient_ = Cli_Create();
-		LOG(ALLOC) << "SNAP7Connection (create) PLC/Cluster: " << thePLC->getName() << "/" << thePLC->theCluster_->getClassName();
-	}
-
+SNAP7Connection::SNAP7Connection(PLC* thePLC) :
+                Connection(thePLC)
+{
+    rackNb_ = 0; //rackNb - common rack is 0 so far
+    slotNb_ = -1; //slotNb - depends on hardware configuration (scan is required the first connect)
 
-	SNAP7Connection::~SNAP7Connection()
-	{
-	    Cli_Destroy(&recvClient_);
-        Cli_Destroy(&sendClient_);
-	}
+    recvClient_ = Cli_Create();
+    sendClient_ = Cli_Create();
 
-	bool SNAP7Connection::open(PLC* thePLC)
-	{
-        int err = 0;
-        bool ret = false;
-        int slotNb;
+    LOG(ALLOC) << "SNAP7Connection (create) PLC/Cluster: " << thePLC->getName() << "/" << thePLC->theCluster_->getClassName();
+}
 
-        //Slot number is not required, so try to connect on different slots (1..31), depending on hardware layout.
-        int *slotsScan;
-        int slotsS7400[4]   = { 3,2,4,1 };    //slot scan - most common layout S7-400
-        int slotsS71x00[4]  = { 1,2,3,4 };    //slot scan - most common layout S7-1200, S7-1500
-        int slotsDefault[4] = { 2,3,4,1 };    //slot scan - most common layout S7-other (S7-300, ET200S)
-        int nbMaxSlot = ((slotNb_ == -1) ? 4 : 1); //slots scan only the first time (slotNb_ == -1)
+SNAP7Connection::~SNAP7Connection()
+{
+    Cli_Destroy(&recvClient_);
+    Cli_Destroy(&sendClient_);
+}
 
+bool SNAP7Connection::open(PLC* thePLC)
+{
+    int err = 0;
+    bool ret = false;
+    int slotNb;
+
+    //Slot number is not required, so try to connect on different slots (1..31), depending on hardware layout.
+    int *slotsScan;
+    int slotsS7400[4] = {3, 2, 4, 1}; //slot scan - most common layout S7-400
+    int slotsS71x00[4] = {1, 2, 3, 4}; //slot scan - most common layout S7-1200, S7-1500
+    int slotsDefault[4] = {2, 3, 4, 1}; //slot scan - most common layout S7-other (S7-300, ET200S)
+    int nbMaxSlot = ( (slotNb_ == -1) ? 4 : 1); //slots scan only the first time (slotNb_ == -1)
+
+    switch (thePLC->getModelID())
+    {
+        case S7400:
+            slotsScan = slotsS7400;
+            break;
+        case S71200:
+        case S71500:
+            slotsScan = slotsS71x00;
+            break;
+        default:
+            slotsScan = slotsDefault; //S7-300, ET200S
+    }
 
+    for (int i = 0; i < nbMaxSlot; i++)
+    {
+        slotNb = slotsScan[i];
 
-        switch (thePLC->getModelID())
-        {
-            case S7400:
-                slotsScan = slotsS7400;    break;
-            case S71200:
-            case S71500:
-                slotsScan = slotsS71x00; break;
-            default:
-                slotsScan = slotsDefault;  //S7-300, ET200S
-        }
+        err = ( (slotNb_ == -1) ? Cli_ConnectTo(recvClient_, thePLC->getIPAddress().c_str(), rackNb_, slotNb) : Cli_Connect(recvClient_));
 
-        for(int i=0; i<nbMaxSlot; i++)
+        if (err == 0)
         {
-            slotNb = slotsScan[i];
+            LOG(DEBUG) << "SNAP7 connect (channel-1) successful on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb_ << "/" << slotNb;
 
-            err = ((slotNb_ == -1) ? Cli_ConnectTo(recvClient_, thePLC->getIPAddress().c_str(), rackNb_, slotNb) :
-                                     Cli_Connect(recvClient_));
+            //We managed to open the first channel, just open the second one on the same slot.
+            err = ( (slotNb_ == -1) ? Cli_ConnectTo(sendClient_, thePLC->getIPAddress().c_str(), rackNb_, slotNb) : Cli_Connect(sendClient_));
 
-            if (err == 0)
+            if (err != 0)
             {
-              LOG(DEBUG) << "SNAP7 connect (channel-1) successful on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb_ << "/" << slotNb;
-
-              //We managed to open the first channel, just open the second one on the same slot.
-              err = ((slotNb_ == -1) ? Cli_ConnectTo(sendClient_, thePLC->getIPAddress().c_str(), rackNb_, slotNb) :
-                                       Cli_Connect(sendClient_));
-
-              if (err != 0)
-              {
-                LOG(DEBUG) << "SNAP7 connection (channel-2) failed on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb_ << "/" << slotNb <<". SNAP7[" << err << "]: " << getSNAP7ErrorMessage(err);
+                LOG(DEBUG) << "SNAP7 connection (channel-2) failed on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb_ << "/" << slotNb << ". SNAP7[" << err << "]: " << getErrorMessage(err);
                 continue;
-              }
+            }
 
-              LOG(DEBUG) << "SNAP7 connect (channel-2) successful on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb_ << "/" << slotNb;
+            LOG(DEBUG) << "SNAP7 connect (channel-2) successful on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb_ << "/" << slotNb;
 
-              slotNb_ = slotNb;  //connection is ok we can store the valid slot number for the next (re)connection (will be faster).
-              ret = true;
-              break;
-            }
-            LOG(DEBUG) << "SNAP7 connection (channel-1) failed on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb_ << "/" << slotNb <<". SNAP7[" << err << "]: " << getSNAP7ErrorMessage(err);
+            slotNb_ = slotNb; //connection is ok we can store the valid slot number for the next (re)connection (will be faster).
+            ret = true;
+            break;
         }
-        return (ret);
-	}
+        LOG(DEBUG) << "SNAP7 connection (channel-1) failed on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb_ << "/" << slotNb << ". SNAP7[" << err << "]: " << getErrorMessage(err);
+    }
+    return (ret);
+}
+
+bool SNAP7Connection::close(PLC* thePLC)
+{
+    bool ret = (Cli_Disconnect(recvClient_) == 0) && (Cli_Disconnect(sendClient_) == 0);
+    return ret;
+}
+
+std::string SNAP7Connection::getErrorMessage(int err)
+{
+    char text[TextLen];
+    Cli_ErrorText(err, text, TextLen);
+    return std::string(text);
+}
 
+//-------------------------------------------------------------------------------------------------------------------
+int SNAP7Connection::readUnitCode(PLC* thePLC, UnitCodeType& dataStruct)
+{
+    int err;
+    TS7OrderCode S7data;
 
-	bool SNAP7Connection::close(PLC* thePLC)
-	{
-		bool ret = (Cli_Disconnect(recvClient_) == 0) &&
-		            (Cli_Disconnect(sendClient_) == 0);
-		return ret;
-	}
+    if ( (err = Cli_GetOrderCode(recvClient_, &S7data)) == 0)
+    {
+        std::ostringstream os;
+        os << S7data.Code;
+        dataStruct.code = os.str();
+        os.str().clear();
+        os << (int)S7data.V1 << "." << (int)S7data.V2 << "." << (int)S7data.V3;
+        dataStruct.version = os.str();
+        LOG(DEBUG) << "Unit order-code received: " << dataStruct.code << ", " << dataStruct.version;
+        return 0;
+    }
+    checkError(thePLC, err, false);
+    return err;
+}
 
+int SNAP7Connection::readUnitStatus(PLC* thePLC, UnitStatusType& dataStruct)
+{
+    int err;
+    int status;
 
-    std::string SNAP7Connection::getSNAP7ErrorMessage(int err)
+    if ( (err = Cli_GetPlcStatus(recvClient_, &status)) == 0)
     {
-        char text[100];
-        Cli_ErrorText(err, text, 100);
-        return std::string(text);
+        dataStruct.status = status;
+        LOG(DEBUG) << "Unit status received: " << (int)dataStruct.status;
+        return 0;
     }
+    checkError(thePLC, err, false);
+    return err;
+}
 
+int SNAP7Connection::readCPUInfo(PLC* thePLC, CPUInfoType& dataStruct)
+{
+    int err;
+    TS7CpuInfo S7data;
 
-    //-------------------------------------------------------------------------------------------------------------------
-    int SNAP7Connection::readUnitCode(PLC* thePLC, UnitCodeType& dataStruct)
+    if ( (err = Cli_GetCpuInfo(recvClient_, &S7data)) == 0)
     {
-        TS7OrderCode S7data;
-        int error = Cli_GetOrderCode(recvClient_, &S7data);
-        if(error)
-        	throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," SNAP7 Error: " + getSNAP7ErrorMessage(error));
-		std::ostringstream os;
-		os << S7data.Code;
-		dataStruct.code = os.str();
-		os.str().clear();
-		os << (int)S7data.V1 << "." << (int)S7data.V2 << "." << (int)S7data.V3;
-		dataStruct.version = os.str();
-		LOG(DEBUG) << "Unit order-code received: " << dataStruct.code << ", " << dataStruct.version;
-		return 0;
+        dataStruct.moduleName = std::string(S7data.ModuleName);
+        dataStruct.moduleTypeName = std::string(S7data.ModuleTypeName);
+        dataStruct.serialNumber = std::string(S7data.SerialNumber);
+        dataStruct.asName = std::string(S7data.ASName);
+        dataStruct.copyright = std::string(S7data.Copyright);
+        LOG(DEBUG) << "CPU info received: " << dataStruct.moduleName << ", " << dataStruct.moduleTypeName << ", " << dataStruct.serialNumber << ", " << dataStruct.asName << ", " << dataStruct.copyright;
+        return 0;
     }
+    checkError(thePLC, err, false);
+    return err;
+}
 
+int SNAP7Connection::readCPInfo(PLC* thePLC, CPInfoType& dataStruct)
+{
+    int err;
+    TS7CpInfo S7data;
 
-    int SNAP7Connection::readUnitStatus(PLC* thePLC, UnitStatusType& dataStruct)
+    if ( (err = Cli_GetCpInfo(recvClient_, &S7data)) == 0)
     {
-        int status;
-        int error = Cli_GetPlcStatus(recvClient_, &status);
-        if(error)
-        	throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," SNAP7 Error: " + getSNAP7ErrorMessage(error));
-		dataStruct.status = status;
-		LOG(DEBUG) << "Unit status received: " << (int)dataStruct.status;
-		return 0;
+        dataStruct.maxPduLength = S7data.MaxPduLengt;
+        dataStruct.maxConnections = S7data.MaxConnections;
+        dataStruct.maxMPIRate = S7data.MaxMpiRate;
+        dataStruct.maxBusRate = S7data.MaxBusRate;
+        LOG(DEBUG) << "CP info received: " << dataStruct.maxPduLength << ", " << dataStruct.maxConnections << ", " << dataStruct.maxMPIRate << ", " << dataStruct.maxBusRate;
+        return 0;
     }
+    checkError(thePLC, err, false);
+    return err;
+}
 
-    int SNAP7Connection::readCPUInfo(PLC* thePLC, CPUInfoType& dataStruct)
+bool SNAP7Connection::isRunning(PLC* thePLC)
+{
+    UnitStatusType statusStruct;
+    this->readUnitStatus(thePLC, statusStruct);
+    switch (statusStruct.status)
     {
-        TS7CpuInfo S7data;
-        int error = Cli_GetCpuInfo(recvClient_, &S7data);
-        if(error)
-        	throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," SNAP7 Error: " + getSNAP7ErrorMessage(error));
-		dataStruct.moduleName = std::string(S7data.ModuleName);
-		dataStruct.moduleTypeName = std::string(S7data.ModuleTypeName);
-		dataStruct.serialNumber = std::string(S7data.SerialNumber);
-		dataStruct.asName = std::string(S7data.ASName);
-		dataStruct.copyright = std::string(S7data.Copyright);
-		LOG(DEBUG) << "CPU info received: " << dataStruct.moduleName << ", " << dataStruct.moduleTypeName << ", "
-				   << dataStruct.serialNumber << ", " << dataStruct.asName << ", " << dataStruct.copyright;
-		return 0;
+        case S7CpuStatusRun:
+            return true;
+        case S7CpuStatusStop:
+            return false;
+        default:
+            throw SilecsException(__FILE__, __LINE__, UNKNOWN_ERROR, std::string("PLC Status is: UNKNOWN"));
     }
+}
 
-    int SNAP7Connection::readCPInfo(PLC* thePLC, CPInfoType& dataStruct)
+//-------------------------------------------------------------------------------------------------------------------
+int SNAP7Connection::readData(PLC* thePLC, unsigned long DBn, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+{
+    int err = 0;
+    //(re)connect the PLC if needed and (re)synchronize the retentive registers
+    if (doOpen(thePLC))
     {
-        TS7CpInfo S7data;
-        int error = Cli_GetCpInfo(recvClient_, &S7data);
-        if(error)
-        	throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," SNAP7 Error: " + getSNAP7ErrorMessage(error));
-		dataStruct.maxPduLength = S7data.MaxPduLengt;
-		dataStruct.maxConnections = S7data.MaxConnections;
-		dataStruct.maxMPIRate = S7data.MaxMpiRate;
-		dataStruct.maxBusRate = S7data.MaxBusRate;
-		LOG(DEBUG) << "CP info received: " << dataStruct.maxPduLength << ", " << dataStruct.maxConnections << ", "
-				   << dataStruct.maxMPIRate << ", " << dataStruct.maxBusRate;
-		return 0;
+        //connection is established then acquire data
+        Lock lock(readMux_);
+
+        //DATA topic makes sense with RECV one
+        if (RECV & Log::topics_)
+            LOG(DATA) << "Read data, DBn: " << DBn << ", ofs: " << offset << ", byte-size: " << size;
+
+        err = Cli_DBRead(recvClient_, (int)DBn, (int)offset, (int)size, (void *)pBuffer);
+        checkError(thePLC, err, false); // close the connection, will try again at the next access
     }
+    return err;
+}
 
-    bool SNAP7Connection::isRunning(PLC* thePLC)
+int SNAP7Connection::writeData(PLC* thePLC, unsigned long DBn, unsigned long offset, unsigned long size, unsigned char* pBuffer)
+{
+    int err = 0;
+    //(re)connect the PLC if needed and (re)synchronize the retentive registers
+    if (doOpen(thePLC))
     {
-		UnitStatusType statusStruct;
-		this->readUnitStatus(thePLC, statusStruct);
-		switch (statusStruct.status)
-		{
-			  case S7CpuStatusRun : return true;
-			  case S7CpuStatusStop: return false;
-			  default             : throw SilecsException(__FILE__, __LINE__, UNKNOWN_ERROR,std::string("PLC Status is: UNKNOWN"));
-		}
+        //connection is established then send data
+        Lock lock(writeMux_);
+
+        //DATA topic makes sense with SEND one
+        if (SEND & Log::topics_)
+            LOG(DATA) << "Write data, DBn: " << DBn << ", ofs: " << offset << ", byte-size: " << size;
+
+        err = Cli_DBWrite(sendClient_, (int)DBn, (int)offset, (int)size, (void *)pBuffer);
+        checkError(thePLC, err, false); // close the connection, will try again at the next access
     }
+    return err;
+}
+
+//-------------------------------------------------------------------------------------------------------------------
+bool SNAP7Connection::checkError(PLC* thePLC, int err, bool retry)
+{
+    if (err != 0)
+    {
+        LOG(COMM) << "Transaction failure with PLC: " << thePLC->getName() << getErrorMessage(err);
 
-    //-------------------------------------------------------------------------------------------------------------------
-	int SNAP7Connection::readData(PLC* thePLC, unsigned long DBn, unsigned long offset, unsigned long size, unsigned char* pBuffer)
-	{
-        //(re)connect the PLC if needed and (re)synchronize the retentive registers
-        if (doOpen(thePLC))
+        if (retry)
         {
-            //connection is established then acquire data
-        	Lock lock(readMux_);
+            LOG(COMM) << "Try to reconnect the PLC: " << thePLC->getName();
+            if (reOpen(thePLC))
+            { // can repeat the request after the connection was successfully reopened
+                return true;
+            }
+            // reconnection has failed again, just close the connection
+            LOG(COMM) << "Unable to reconnect the PLC: " << thePLC->getName();
+        }
+        // no retry, we just want to close (use default case)
+        doClose(thePLC, /*withLock =*/true);
+    }
+    return false;
+}
 
-			//DATA topic makes sense with RECV one
-			if (RECV & Log::topics_) LOG(DATA) << "Read data, DBn: " << DBn << ", ofs: " << offset << ", byte-size: " << size;
+int SNAP7Connection::coldRestart(PLC* thePLC)
+{
+    if (doOpen(thePLC))
+    {
+        Lock lock(writeMux_);
+        int error = Cli_PlcColdStart(sendClient_);
+        if (error)
+            throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR, " SNAP7 Error: " + getErrorMessage(error));
 
-			int error = Cli_DBRead(recvClient_, (int)DBn, (int)offset, (int)size, (void *)pBuffer);
-	        if(error)
-	        	throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," SNAP7 Error: " + getSNAP7ErrorMessage(error));
-        }
-		return 0;
-	}
-
-	int SNAP7Connection::writeData(PLC* thePLC, unsigned long DBn, unsigned long offset, unsigned long size, unsigned char* pBuffer)
-	{
-		//(re)connect the PLC if needed and (re)synchronize the retentive registers
-		if (doOpen(thePLC))
-		{
-			//connection is established then send data
-			Lock lock(writeMux_);
-
-			//DATA topic makes sense with SEND one
-			if (SEND & Log::topics_) LOG(DATA) << "Write data, DBn: " << DBn << ", ofs: " << offset << ", byte-size: " << size;
-
-			int error = Cli_DBWrite(sendClient_, (int)DBn, (int)offset, (int)size, (void *)pBuffer);
-	        if(error)
-	        	throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," SNAP7 Error: " + getSNAP7ErrorMessage(error));
-		}
-		return 0;
-	}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-	//Puts the CPU in RUN mode performing a COLD START.
-	int SNAP7Connection::coldRestart(PLC* thePLC)
-	{
-		if(doOpen(thePLC))
-		{
-			Lock lock(writeMux_);
-			int error = Cli_PlcColdStart(sendClient_);
-			if(error)
-				throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," SNAP7 Error: " + getSNAP7ErrorMessage(error));
-
-		}
-		return 0;
-	}
-
-	//Puts the CPU in STOP mode.
-		int SNAP7Connection::plcStop(PLC* thePLC)
-		{
-			if(doOpen(thePLC))
-			{
-				Lock lock(writeMux_);
-				int error = Cli_PlcStop(sendClient_);
-				if(error)
-					throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR," SNAP7 Error: " + getSNAP7ErrorMessage(error));
-
-			}
-			return 0;
-		}
-//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    }
+    return 0;
+}
+
+int SNAP7Connection::plcStop(PLC* thePLC)
+{
+    if (doOpen(thePLC))
+    {
+        Lock lock(writeMux_);
+        int error = Cli_PlcStop(sendClient_);
+        if (error)
+            throw SilecsException(__FILE__, __LINE__, UNEXPECTED_ERROR, " SNAP7 Error: " + getErrorMessage(error));
 
+    }
+    return 0;
+}
 
-} // namespace
+}// namespace
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.h
index 6bb7ee1f74900b50dd4275b1959c35b6c1302990..ea2b9ced9a258af7c7ccf4588f0a5d1f664a0e84 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.h
@@ -57,7 +57,8 @@ namespace Silecs
         int rackNb_; //rackNb - common rack is 0 by default
         int slotNb_; //slotNb - depends on hardware configuration (scan is required the first connect)
 
-	    std::string getSNAP7ErrorMessage(int err);
+	    std::string getErrorMessage(int err);
+	    bool checkError(PLC* thePLC, int err, bool retry);
 	};
 
 } // namespace
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Hardware.cpp b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Hardware.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a19ef7d4109a45c6332f1ce0ac347d837f4cb2d4
--- /dev/null
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Hardware.cpp
@@ -0,0 +1,75 @@
+// Copyright 2016 CERN and GSI
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "SNAP7Hardware.h"
+
+/*----------------------------------------------------------*/
+/* Time funtion
+ * IeRfcSetTime: Convert lynxos time_t format to PLC _DT format
+ * (SIMATIC).
+ *
+ * Details:
+ * PLC DATE_AND_TIME (or DT) format is coded on 8 byte in BCD
+ * format:
+ * 0      1      2      3      4      5      6       7
+ * YY     MM     DD     HH     MN     SC     SC/100  SC/10e4
+ */
+void IeRfcSetTime(unsigned char *dt, time_t epoch)  // to PLC
+{
+  struct tm *dscst;
+  dscst = localtime(&epoch);
+
+  dt[7] = 0;   // not used at the moment
+  dt[6] = 0;   // not used at the moment
+  dt[5] = _tobcd(dscst->tm_sec);
+  dt[4] = _tobcd(dscst->tm_min);
+  dt[3] = _tobcd(dscst->tm_hour);
+  dt[2] = _tobcd(dscst->tm_mday);
+  dt[1] = _tobcd(dscst->tm_mon+1);
+  dt[0] = _tobcd(dscst->tm_year-100);
+}
+
+/*----------------------------------------------------------*/
+/* Time funtion
+ * IeRfcGetTime: Convert PLC _DT format to time_t format (SIMATIC).
+ *
+ * Details:
+ * PLC DATE_AND_TIME (or DT) format is coded on 8 byte in BCD
+ * format:
+ * 0      1      2      3      4      5      6       7
+ * YY     MM     DD     HH     MN     SC     SC/100  SC/10e4
+ */
+double IeRfcGetTime(unsigned char *dt) // from PLC
+{
+    struct tm plcst;
+    time_t plctm;
+    double ms;
+    int year;
+
+  plcst.tm_sec  = _frombcd(dt[5]);
+  plcst.tm_min  = _frombcd(dt[4]);
+  plcst.tm_hour = _frombcd(dt[3]);
+  plcst.tm_mday = _frombcd(dt[2]);
+  plcst.tm_mon  = _frombcd(dt[1])-1;
+  year = _frombcd(dt[0]);
+  //look at Siemens DATA_AND_TIME type documentation
+  plcst.tm_year = ((year >= 90) ? year : year+100);
+
+  ms = ((double)_frombcd(dt[6])/100.)+((double)_frombcd(dt[7])/10000.);
+  plcst.tm_isdst = -1; // daylight saving time unavailable
+  plctm = mktime(&plcst);
+
+  return((double)plctm + ms);
+}
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Hardware.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Hardware.h
new file mode 100644
index 0000000000000000000000000000000000000000..87336b642d015f787a2d188b5537cfc645f3e26d
--- /dev/null
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Hardware.h
@@ -0,0 +1,47 @@
+// Copyright 2016 CERN and GSI
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#ifndef _SNAP7HARDWARE_H_
+#define _SNAP7HARDWARE_H_
+
+#include <silecs-communication/protocol/core/ietype.h>
+
+/*----------------------------------------------------------*/
+/* Time funtion
+ * IeRfcSetTime: Convert time_t epoch date to PLC _DT format
+ * (SIMATIC).
+ *
+ * Details:
+ * PLC DATE_AND_TIME (or DT) format is coded on 8 byte in BCD
+ * format:
+ * 0      1      2      3      4      5      6       7
+ * YY     MM     DD     HH     MN     SC     SC/100  SC/10e4
+ */
+void IeRfcSetTime(unsigned char *dt, time_t epoch);  // to PLC
+
+/*----------------------------------------------------------*/
+/* Time funtion
+ * IeRfcGetTime: Convert PLC _DT format to lynxOS time_t format
+ * (SIMATIC).
+ *
+ * Details:
+ * PLC DATE_AND_TIME (or DT) format is coded on 8 byte in BCD
+ * format:
+ * 0      1      2      3      4      5      6       7
+ * YY     MM     DD     HH     MN     SC     SC/100  SC/10e4
+ */
+double IeRfcGetTime(unsigned char *dt); // from PLC
+
+
+#endif /* _SNAP7HARDWARE_H_ */
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.cpp b/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.cpp
index b0725325d571f51ebdc27ce2cad295386a12a551..7c4eaabf368e8578107feb73c154492b15aeba31 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.cpp
@@ -13,6 +13,9 @@
 // You should have received a copy of the GNU General Public License
 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+#include <fcntl.h>
+#include <signal.h>
+
 #include <silecs-communication/interface/equipment/SilecsCluster.h>
 #include <silecs-communication/interface/utility/SilecsLog.h>
 #include <silecs-communication/interface/communication/SilecsConnection.h>
@@ -113,7 +116,7 @@ namespace Silecs
 
 			if (isTimeToReconnect())
 			{
-                if (isReachable = (IeRfcPing((char *) thePLC->getName().c_str(), NULL) == 0))
+                if (isReachable = (ping((char *) thePLC->getName().c_str(), NULL) == 0))
                 {
                     LOG((COMM|DIAG)) << "It's time to reconnect";
 
@@ -235,7 +238,7 @@ namespace Silecs
 	//------------------------------------------------------------------------------------------------------------------------------------------------
 	bool Connection::reOpen(PLC* thePLC)
 	{
-		if (IeRfcPing((char *) thePLC->getName().c_str(), 0) == 0)
+		if (ping((char *) thePLC->getName().c_str(), 0) == 0)
 		{	doClose(thePLC, /*withLock =*/true);
 			return doOpen(thePLC);
 		}
@@ -404,5 +407,166 @@ namespace Silecs
 		}
 		return toBeReconnected;
 	}
+	  /* This macro is used to trap the unexpected broken pipe and
+	     return an error instead of exit process.
+	  */
+	  static __sighandler_t sigpipeHandler = (__sighandler_t)-1;
+	  #define _DISABLE_SIGPIPE sigpipeHandler = signal(SIGPIPE, SIG_IGN)
+	  #define _ENABLE_SIGPIPE signal(SIGPIPE, sigpipeHandler)
+
+	  /*----------------------------------------------------------*/
+	  /* This is a function used to connect an host on a port.
+	   * 'ip' is the ip address string
+	   * 'port' is the port number (102 for rfc1006 server)
+	   * 'dst' is the TSAP destination string (exp: "TCP-1")
+	   * 'src' is the TSAP source string (exp: "TCP-1")
+	   * 'ts' timeout in second (1s minimum)
+	   * return a socket descriptor or <0 on error
+	   * (see constant error)
+	   *
+	   * Details:
+	   * intermediate connect_nonb() function is used to perform a non-blockant connection.
+	   * intermediate rfcPing() function is used to check if PLC is ON
+	   */
+	  int connect_nonb(int sockfd, struct sockaddr *saptr, socklen_t salen, int nsec)
+	  {
+	    int             flags, n, error;
+	    socklen_t       len;
+	    fd_set          rset, wset;
+	    struct timeval  tval;
+
+	    flags = fcntl(sockfd, F_GETFL, 0);
+	    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+
+	    error = 0;
+	    /*v1.1*/
+	    _DISABLE_SIGPIPE;
+	    n = connect(sockfd, (struct sockaddr *) saptr, salen);
+	    _ENABLE_SIGPIPE;
+	    if (n < 0){
+	        if (errno != EINPROGRESS)
+	            return(-1);
+	    }
+
+	    /* Do whatever we want while the connect is taking place. */
+
+	    if (n == 0)
+	        goto done;  /* connect completed immediately */
+
+	    FD_ZERO(&rset);
+	    FD_SET(sockfd, &rset);
+	    wset = rset;
+	    tval.tv_sec = nsec;
+	    tval.tv_usec = 0;
+
+	    if ( (n = select(sockfd+1, &rset, &wset, NULL,
+	                     nsec ? &tval : NULL)) == 0) {
+	        close(sockfd);      /* timeout */
+	        errno = ETIMEDOUT;
+	        return(-1);
+	    }
+
+	    if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
+	        len = sizeof(error);
+	        if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+	            return(-1);         /* Solaris pending error */
+	        }
+	    }
+
+	  done:
+	    fcntl(sockfd, F_SETFL, flags);  /* restore file status flags */
+
+	    if (error) {
+	        /*close(sockfd); just in case */
+	        errno = error;
+	        return(-1);
+	    }
+
+	    return(0);
+	  }
+
+	  /*----------------------------------------------------------*/
+	  int rfcPing(char *ip, long ts)
+	  {
+	    int err, s, val = 1;
+	    struct protoent *pent;
+	    struct sockaddr_in rsock;
+
+	    /* Socket create/connect */
+	    memset ((char *)&rsock,0,sizeof(rsock));
+
+	    if ((s=socket(AF_INET,SOCK_STREAM,0)) == -1)
+	    {
+	      #ifdef COMMENT
+	        printf("#Error - Can't create socket: %s\n", strerror(errno));
+	      #endif
+	        return RFC_SYS_ERROR;
+	    }
+
+	    /* Set TCP_NODELAY option to force immediate TCP/IP acknowledgement */
+	    if ((pent=getprotobyname("TCP")) == NULL)
+	    {
+	      #ifdef COMMENT
+	        printf("#Error - Can't configure socket: %s\n", strerror(errno));
+	      #endif
+	        return RFC_SYS_ERROR;
+	    }
+	    if (setsockopt(s,pent->p_proto,TCP_NODELAY,&val,4) == -1)
+	    {
+	      #ifdef COMMENT
+	        printf("#Error - Can't configure socket: %s\n", strerror(errno));
+	      #endif
+	        return RFC_SYS_ERROR;
+	    }
+
+	    #ifdef COMMENT
+	    printf("#Comment - Socket created: %i\n", s);
+	    #endif
+
+	    rsock.sin_addr.s_addr=inet_addr(ip);
+	    rsock.sin_family=AF_INET;
+	    /*check any port to detect if the host is OFF*/
+	    rsock.sin_port=htons(102);
+
+	    err = 0;
+	    if (connect_nonb(s,(struct sockaddr *)(&rsock),sizeof(rsock), ts) == -1)
+	    {
+	      /*if hostname is OFF, connect() fails on TIMEOUT*/
+	        if ((errno == ETIMEDOUT) || (errno == EHOSTDOWN) || (errno == EHOSTUNREACH)) {
+	        err = RFC_TIMEOUT_ERROR;
+	      }
+	    }
+
+	        close(s);
+	    return err;
+	  }
+
+	  /*..........................................................*/
+	  int ping(char *hostName, char *plcIP)
+	  {
+	    struct in_addr addr;
+	    struct hostent *hp;
+	    char *ipstr = plcIP;
+
+	    if ((hostName == NULL) && (plcIP == NULL))
+	      return(IE_PARAM_ERROR);
+
+	    // use hostName reference in priority else plcIP
+	    if (hostName)
+	    {
+	      hp = gethostbyname(hostName);
+	        if (hp)
+	        {
+	          addr.s_addr = *((unsigned long int *) hp->h_addr);
+	          ipstr = inet_ntoa(addr);
+	        }
+	    }
+
+	    if (ipstr == NULL)
+	    return(IE_HOST_UNKNOWN_ERROR);
+
+	    /*trying to connect PLC (1 second max)*/
+	    return (rfcPing(ipstr, 1));
+	  }
 
 } // end namespace
diff --git a/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.h b/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.h
index 7d350c76dc6782808f8bb5b1e4edb9aa7a8053c6..c87cf3adf5259e7fe0710cb7c7b734f6696a528c 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SilecsConnection.h
@@ -160,6 +160,11 @@ namespace Silecs
 		unsigned long remainConn_;  //number of attempt before next slow-down
 		static const unsigned int numberConn_; //number of connection attempt for each connection delay
 
+	    /* ping function is a function used to check
+	     * if PLC is ON (~ping) before trying to connect it.
+	     */
+	    static int ping(char *hostName, char *plcIP);
+
 		// Communication Diagnostic & Monitoring
 		static bool isAlive_; // PLC has repliyed to the ping: true/false
 		bool isConnected_; // State of this particular connection: FEC/PLC/Class
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 69a32c5116d54f1f2ce6dd64d4ac8b1e8513fb88..2c06112a60255c576ae70299b8f22b354b7f2e2d 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/PLCRegister.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/PLCRegister.cpp
@@ -16,6 +16,8 @@
 #include "PLCRegister.h"
 #include <silecs-communication/protocol/core/silecs.h>
 #include <silecs-communication/protocol/modbus/iemdb.h>
+#include <silecs-communication/interface/communication/MBHardware.h>
+#include <silecs-communication/interface/communication/SNAP7Hardware.h>
 
 namespace Silecs
 {
diff --git a/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.cpp b/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.cpp
index bf98923c37f4825e417fb27987c2911226cb3ebe..ca0bbabe389cbd6c1c270a5cd5343529a3ec2fdd 100644
--- a/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.cpp
@@ -43,227 +43,6 @@
 /* MACRO DEFINITION																				  */
 /* ---------------------------------------------------------*/
 
-/* This macro is used to trap the unexpected broken pipe and
-   return an error instead of exit process.
-*/
-static __sighandler_t sigpipeHandler = (__sighandler_t)-1;
-#define _DISABLE_SIGPIPE sigpipeHandler = signal(SIGPIPE, SIG_IGN)
-#define _ENABLE_SIGPIPE signal(SIGPIPE, sigpipeHandler)
-
-/*----------------------------------------------------------*/
-/* Time funtion
- * IeRfcSetTime: Convert lynxos time_t format to PLC _DT format
- * (SIMATIC).
- *
- * Details:
- * PLC DATE_AND_TIME (or DT) format is coded on 8 byte in BCD
- * format:
- * 0      1      2      3      4      5      6       7
- * YY     MM     DD     HH     MN     SC     SC/100  SC/10e4
- */
-void IeRfcSetTime(unsigned char *dt, time_t epoch)  // to PLC
-{
-  struct tm *dscst;
-  dscst = localtime(&epoch);
-
-  dt[7] = 0;   // not used at the moment
-  dt[6] = 0;   // not used at the moment
-  dt[5] = _tobcd(dscst->tm_sec);
-  dt[4] = _tobcd(dscst->tm_min);
-  dt[3] = _tobcd(dscst->tm_hour);
-  dt[2] = _tobcd(dscst->tm_mday);
-  dt[1] = _tobcd(dscst->tm_mon+1);
-  dt[0] = _tobcd(dscst->tm_year-100);
-}
-
-/*----------------------------------------------------------*/
-/* Time funtion
- * IeRfcGetTime: Convert PLC _DT format to time_t format (SIMATIC).
- *
- * Details:
- * PLC DATE_AND_TIME (or DT) format is coded on 8 byte in BCD
- * format:
- * 0      1      2      3      4      5      6       7
- * YY     MM     DD     HH     MN     SC     SC/100  SC/10e4
- */
-double IeRfcGetTime(unsigned char *dt) // from PLC
-{
-	struct tm plcst;
-	time_t plctm;
-	double ms;
-	int year;
-
-  plcst.tm_sec  = _frombcd(dt[5]);
-  plcst.tm_min  = _frombcd(dt[4]);
-  plcst.tm_hour = _frombcd(dt[3]);
-  plcst.tm_mday = _frombcd(dt[2]);
-  plcst.tm_mon  = _frombcd(dt[1])-1;
-  year = _frombcd(dt[0]);
-  //look at Siemens DATA_AND_TIME type documentation
-  plcst.tm_year = ((year >= 90) ? year : year+100);
-
-  ms = ((double)_frombcd(dt[6])/100.)+((double)_frombcd(dt[7])/10000.);
-  plcst.tm_isdst = -1; // daylight saving time unavailable
-  plctm = mktime(&plcst);
-
-  return((double)plctm + ms);
-}
-
-/*----------------------------------------------------------*/
-/* This is a function used to connect an host on a port.
- * 'ip' is the ip address string
- * 'port' is the port number (102 for rfc1006 server)
- * 'dst' is the TSAP destination string (exp: "TCP-1")
- * 'src' is the TSAP source string (exp: "TCP-1")
- * 'ts' timeout in second (1s minimum)
- * return a socket descriptor or <0 on error
- * (see constant error)
- *
- * Details:
- * intermediate connect_nonb() function is used to perform a non-blockant connection.
- * intermediate rfcPing() function is used to check if PLC is ON
- */
-int connect_nonb(int sockfd, struct sockaddr *saptr, socklen_t salen, int nsec)
-{
-	int				flags, n, error;
-	socklen_t		len;
-	fd_set			rset, wset;
-	struct timeval	tval;
-
-	flags = fcntl(sockfd, F_GETFL, 0);
-	fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
-
-	error = 0;
-  /*v1.1*/
-  _DISABLE_SIGPIPE;
-	n = connect(sockfd, (struct sockaddr *) saptr, salen);
-  _ENABLE_SIGPIPE;
-	if (n < 0){
-		if (errno != EINPROGRESS)
-			return(-1);
-	}
-
-	/* Do whatever we want while the connect is taking place. */
-
-	if (n == 0)
-		goto done;	/* connect completed immediately */
-
-	FD_ZERO(&rset);
-	FD_SET(sockfd, &rset);
-	wset = rset;
-	tval.tv_sec = nsec;
-	tval.tv_usec = 0;
-
-	if ( (n = select(sockfd+1, &rset, &wset, NULL,
-					 nsec ? &tval : NULL)) == 0) {
-		close(sockfd);		/* timeout */
-		errno = ETIMEDOUT;
-		return(-1);
-	}
-
-	if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
-		len = sizeof(error);
-		if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
-			return(-1);			/* Solaris pending error */
-		}
-	}
-
-done:
-	fcntl(sockfd, F_SETFL, flags);	/* restore file status flags */
-
-	if (error) {
-		/*close(sockfd); just in case */
-		errno = error;
-		return(-1);
-	}
-
-	return(0);
-}
-
-/*----------------------------------------------------------*/
-int rfcPing(char *ip, long ts)
-{
-	int err, s, val = 1;
-	struct protoent *pent;
-	struct sockaddr_in rsock;
-
-	/* Socket create/connect */
-	memset ((char *)&rsock,0,sizeof(rsock));
-
-	if ((s=socket(AF_INET,SOCK_STREAM,0)) == -1)
-	{
-	  #ifdef COMMENT
-		printf("#Error - Can't create socket: %s\n", strerror(errno));
-	  #endif
-		return RFC_SYS_ERROR;
-	}
-
-	/* Set TCP_NODELAY option to force immediate TCP/IP acknowledgement */
-	if ((pent=getprotobyname("TCP")) == NULL)
-	{
-	  #ifdef COMMENT
-		printf("#Error - Can't configure socket: %s\n", strerror(errno));
-	  #endif
-		return RFC_SYS_ERROR;
-	}
-	if (setsockopt(s,pent->p_proto,TCP_NODELAY,&val,4) == -1)
-	{
-	  #ifdef COMMENT
-		printf("#Error - Can't configure socket: %s\n", strerror(errno));
-	  #endif
-		return RFC_SYS_ERROR;
-	}
-
-	#ifdef COMMENT
-	printf("#Comment - Socket created: %i\n", s);
-	#endif
-
-	rsock.sin_addr.s_addr=inet_addr(ip);
-	rsock.sin_family=AF_INET;
-	/*check any port to detect if the host is OFF*/
-	rsock.sin_port=htons(102);
-
-	err = 0;
-	if (connect_nonb(s,(struct sockaddr *)(&rsock),sizeof(rsock), ts) == -1)
-	{
-	  /*if hostname is OFF, connect() fails on TIMEOUT*/
-      if ((errno == ETIMEDOUT) || (errno == EHOSTDOWN) || (errno == EHOSTUNREACH)) {
-	  	err = RFC_TIMEOUT_ERROR;
-	  }
-	}
-
-  	close(s);
-	return err;
-}
-
-/*..........................................................*/
-int IeRfcPing (char *hostName, char *plcIP)
-{
-  struct in_addr addr;
-  struct hostent *hp;
-  char *ipstr = plcIP;
-
-  if ((hostName == NULL) && (plcIP == NULL))
-	  return(IE_PARAM_ERROR);
-
-  // use hostName reference in priority else plcIP
-  if (hostName)
-	{
-	  hp = gethostbyname(hostName);
-		if (hp)
-		{
-		  addr.s_addr = *((unsigned long int *) hp->h_addr);
-		  ipstr = inet_ntoa(addr);
-		}
-	}
-
-  if (ipstr == NULL)
- 	return(IE_HOST_UNKNOWN_ERROR);
-
-  /*trying to connect PLC (1 second max)*/
-  return (rfcPing(ipstr, 1));
-}
-
 /*----------------------------------------------------------*/
 /* This function return the string which describes the
  * error given by 'error' parameter.
@@ -278,32 +57,16 @@ char *IeGetErrorMessage(int err)
 
   static struct
   {
-	int ie_code;
-	char * ie_mes;
+    int ie_code;
+    char * ie_mes;
   } errorMap[] =
   {
-	{IE_SYS_ERROR, "[RFC lib.] function system error"},
-	{IE_PARAM_ERROR, "[IE/RFC lib.] bad parameter(s) value/format"},
-	{IE_CONNECT_ERROR, "[RFC lib.] PLC connection failed"},
-	{IE_DISCONNECT_ERROR, "[RFC lib.] PLC disconnection requested"},
-	{IE_TIMEOUT_ERROR, "[RFC lib.] communication (connect/send/recv) timeout occurred"},
-	{IE_EPIPE_ERROR, "[RFC lib.] PLC communication broken"},
-	{IE_FRAME_ERROR, "[RFC lib.] PLC data frame error"},
-	{IE_DEFER_CMD_BUFFER_FULL, "[IE lib.] deferred commands buffer overflow"},
-	{IE_DEFER_REP_BUFFER_EMPTY, "[IE lib.] deferred replies empty"},
-	{IE_BLOCK_SIZE_ERROR, "[IE lib.] block size exceed PLC memory allocation"},
-	{IE_NB_MONITORING_ERROR, "[IE lib.] monitoring descriptor out of limit"},
-	{IE_HOST_PING_ERROR, "[IE lib.] PLC does not reply to ping"},
-	{IE_HOST_UNKNOWN_ERROR, "[IE lib.] PLC hostname unknown"},
-	{IE_CONFIG_FILE_ERROR, "[IE lib.] pair PLC/FEC not found in the config. file"},
-	{IE_EQUIPMENT_UNKNOWN_ERROR, "[PLC] equipment id (devclass+eqp) unknown"},
-	{IE_MEMORY_OVERFLOW_ERROR, "[PLC] get data buffer overflow"},
-	{IE_ACCESS_VIOLATION_ERROR, "[PLC] DB unknown or get/set access violation"},
-	{IE_MD_MONITORING_ERROR, "[PLC] bad monitoring descriptor or already used"},
-	{IE_ALLOC_MONITORING_ERROR, "[PLC] monitoring record allocation failed"},
-	{IE_UNALLOC_MONITORING_ERROR, "[PLC] monitoring record unallocation failed"},
-	{IE_SET_TIME_IOCTL_ERROR, "[PLC] PLC date and time setting failed"},
-	{IE_KEEP_ALIVE_IOCTL_ERROR, "[PLC] PLC keep-alive transactions failed"},
+  {IE_SYS_ERROR, "[RFC lib.] function system error"}, //unused
+  {IE_PARAM_ERROR, "[IE/RFC lib.] bad parameter(s) value/format"}, //used by Silecs
+    {IE_CONNECT_ERROR, "[RFC lib.] PLC connection failed"}, //unused
+    {IE_DISCONNECT_ERROR, "[RFC lib.] PLC disconnection requested"}, //unused
+    {IE_TIMEOUT_ERROR, "[RFC lib.] communication (connect/send/recv) timeout occurred"}, //used by Snap7
+    {IE_HOST_UNKNOWN_ERROR, "[IE lib.] PLC hostname unknown"}, //used by Silecs, PlcSendAction and PlcRcvAction
   };
 
   static int errorMapSize = sizeof(errorMap)/sizeof(errorMap[0]);
diff --git a/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.h b/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.h
index 34ecce74045c0c26a8b2caac59966b23f4049922..50a466609940b49ec0f9648cc6b0d749db1d91e6 100644
--- a/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.h
+++ b/silecs-communication-cpp/src/silecs-communication/protocol/core/silecs.h
@@ -38,38 +38,6 @@
 /* ---------------------------------------------------------*/
 #include "ietype.h"
 
-/*----------------------------------------------------------*/
-/* Time funtion
- * IeRfcSetTime: Convert time_t epoch date to PLC _DT format
- * (SIMATIC).
- *
- * Details:
- * PLC DATE_AND_TIME (or DT) format is coded on 8 byte in BCD
- * format:
- * 0      1      2      3      4      5      6       7
- * YY     MM     DD     HH     MN     SC     SC/100  SC/10e4
- */
-void IeRfcSetTime(unsigned char *dt, time_t epoch);  // to PLC
-
-/*----------------------------------------------------------*/
-/* Time funtion
- * IeRfcGetTime: Convert PLC _DT format to lynxOS time_t format
- * (SIMATIC).
- *
- * Details:
- * PLC DATE_AND_TIME (or DT) format is coded on 8 byte in BCD
- * format:
- * 0      1      2      3      4      5      6       7
- * YY     MM     DD     HH     MN     SC     SC/100  SC/10e4
- */
-double IeRfcGetTime(unsigned char *dt); // from PLC
-
-/*----------------------------------------------------------*/
-/* IeRfcPing function is a function used to check
- * if PLC is ON (~ping) before trying to connect it.
- */
-int IeRfcPing (char *hostName, char *plcIP);
-
 /*----------------------------------------------------------*/
 /* This function return the string which describes the
  * error given by 'error' parameter.
diff --git a/silecs-communication-cpp/src/silecs-communication/protocol/modbus/iemdb.cpp b/silecs-communication-cpp/src/silecs-communication/protocol/modbus/iemdb.cpp
index 58b27220eee61cdcf4ffad61017764a6f3b455e0..7439990ce71b77522195023ab88267183c93e84d 100644
--- a/silecs-communication-cpp/src/silecs-communication/protocol/modbus/iemdb.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/protocol/modbus/iemdb.cpp
@@ -1,9 +1,6 @@
 #ifdef MODBUS_SUPPORT_ENABLED
 #include "iemdb.h"
 #include <modbus.h>
-//Modbus max data size definition (byte counting)
-#define MAX_WRITE_DATA_SIZE MODBUS_MAX_WRITE_REGISTERS*2
-#define MAX_READ_DATA_SIZE  MODBUS_MAX_READ_REGISTERS*2
 
 /* ---------------------------------------------------------*/
 /* FUNCTIONS CODE											*/
@@ -27,145 +24,4 @@ static inline struct timespec d_to_timespec(double time) {
 /*----------------------------------------------------------*/
 /* Glocal functions                                         */
 /* ---------------------------------------------------------*/
-
-/*----------------------------------------------------------*/
-/* Time funtion
- * IeMdbSetTime: Convert lynxos time_t format to PLC SCHNEIDER
- * format.
- *
- * Details:
- * PLC SCHNEIER format is coded on 8 bytes BCD
- * format:
- *
- *  0      1      2      3      4      5     6     7
- *  SC     00     HH     MN     MM     DD    YY	   YY
- *
- *  byte 1 is used by gateway to synchronize time setting.
- */
-void IeMdbSetTime(unsigned char *dt, time_t epoch)  // to PLC
-{
-  struct tm *dscst;
-  dscst = localtime(&epoch);
-
-  /*v1.7*/
-  /*In fact, each 16bits word is swapped with SCHNEIDER PLC
-    1      0      3      2      5      4     7     6
-    SC     00     HH     MN     MM     DD    YY	   YY
-
-	Swapping can do it directly during data transferring
-  */
-
-  dt[1] = _tobcd(dscst->tm_sec);
-  dt[0] = 0x00; /*not used*/
-  dt[3] = _tobcd(dscst->tm_hour);
-  dt[2] = _tobcd(dscst->tm_min);
-  dt[5] = _tobcd(dscst->tm_mon+1);
-  dt[4] = _tobcd(dscst->tm_mday);
-  dt[7] = _tobcd(2000/100);
-  dt[6] = _tobcd(dscst->tm_year-100);
-}
-
-/*----------------------------------------------------------*/
-/* Time funtion
- * IeMdbGetTime: Convert PLC SCHNEIDER format to time_t format.
- *
- * Details:
- * PLC SCHNEIER format is coded on 8 bytes BCD
- * format:
- *
- *  0      1        2      3      4      5     6     7
- *  SC     SC/100   HH     MN     MM     DD    YY	 YY
- *
- */
-double IeMdbGetTime(unsigned char *dt) // from PLC
-{
-  struct tm plcst;
-  time_t plctm;
-  double ms;
-  int year;
-
-  /*In fact, each 16bits word is swapped with SCHNEIDER PLC
-    1      0        3      2      5      4     7     6
-    SC     SC/100   HH     MN     MM     DD    YY	 YY
-
-	Swapping can do it directly during data transferring
-  */
-
-  plcst.tm_sec  = _frombcd(dt[1]);
-  plcst.tm_hour = _frombcd(dt[3]);
-  plcst.tm_min  = _frombcd(dt[2]);
-  plcst.tm_mon  = _frombcd(dt[5])-1;
-  plcst.tm_mday = _frombcd(dt[4]);
-  year = _frombcd(dt[6]);
-  //look at Schneider DATA_AND_TIME type documentation
-  plcst.tm_year = ((year >= 90) ? year : year+100);
-  /*plcst.tm_wday = no used in PLC*/
-  /*plcst.tm_yday = no used in PLC*/
-
-  ms = ((double)_frombcd(dt[0])/100.);
-  plcst.tm_isdst = -1; // daylight saving time unavailable
-  plctm = mktime(&plcst);
-
-  return((double)plctm + ms);
-}
-
-/*----------------------------------------------------------*/
-int IeMBwriteData(modbus_t* ctx, uint16_t start_addr, uint16_t count, uint8_t* data)
-{
-    uint16_t *srcp = (uint16_t*)data;
-    int word_count, byte_count;
-
-    while(count)
-    {
-        word_count = (count > MAX_WRITE_DATA_SIZE) ? MAX_WRITE_DATA_SIZE/2 : (count/2)+(count%2);
-        byte_count = (word_count * 2);
-
-        if (modbus_write_registers(ctx, start_addr, word_count, srcp) != word_count)
-        {
-            return IE_EPIPE_ERROR;
-        }
-
-        //srcp += byte_count-(count%2);
-        srcp += word_count;
-        start_addr += word_count;
-        count -= (byte_count - (count%2));
-    }
-
-    return 0;
-}
-
-/*----------------------------------------------------------*/
-int IeMBreadData(modbus_t* ctx, uint16_t start_addr, uint16_t count, uint8_t* data)
-{
-  uint16_t *destp = (uint16_t*)data;
-  int word_count, byte_count;
-
-  while(count) {
-
-      if (count > MAX_READ_DATA_SIZE)
-      {
-         /*'word_count' is a word counter*/
-         word_count = MAX_READ_DATA_SIZE/2;
-      }
-      else
-      {
-        /*'word_count' is a word counter*/
-        word_count = (count/2) + (count%2);
-      }
-
-      byte_count = (word_count * 2);
-
-      if (modbus_read_registers(ctx, start_addr, word_count, destp) != word_count)
-      {
-          return IE_EPIPE_ERROR;
-      }
-
-      //destp += (byte_count-(count%2));
-      destp += word_count;
-      start_addr += word_count;
-      count -= (byte_count - (count%2));
-  }
-
-  return 0;
-}
 #endif //MODBUS_SUPPORT_ENABLED