From c717c16f5d2ba46abf36efad80c76643a08e003c Mon Sep 17 00:00:00 2001
From: aschwinn <al.schwinn@gsi.de>
Date: Fri, 21 Jul 2017 15:49:34 +0200
Subject: [PATCH] [SIL-228] Connection rejected for S7-400 controllers
 installed in slot 2

---
 .../communication/SNAP7Connection.cpp         | 57 ++++++++++++-------
 .../interface/communication/SNAP7Connection.h |  3 +
 2 files changed, 39 insertions(+), 21 deletions(-)

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 6f91e02..277098c 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.cpp
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.cpp
@@ -25,6 +25,9 @@ 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();
@@ -40,14 +43,17 @@ namespace Silecs
 	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,4,2,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 rackNb = 0;                              //rackNb - common rack is 0 so far
-        int slotNb;
+        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())
         {
@@ -60,27 +66,36 @@ namespace Silecs
                 slotsScan = slotsDefault;  //S7-300, ET200S
         }
 
-        for(int i=0; i<4; i++)
+        for(int i=0; i<nbMaxSlot; i++)
         {
             slotNb = slotsScan[i];
-            err = Cli_ConnectTo(recvClient_, thePLC->getIPAddress().c_str(), rackNb, slotNb);
-            if (err) // next slot
-            {
-            	LOG(DEBUG) << "SNAP7 connection (channel-2) failed on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb << "/" << slotNb <<". SNAP7[" << err << "]: " << getSNAP7ErrorMessage(err);
-            	break;
-            }
-            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 = Cli_ConnectTo(sendClient_, thePLC->getIPAddress().c_str(), rackNb, slotNb);
-            if (err) // next slot
+
+            err = ((slotNb_ == -1) ? Cli_ConnectTo(recvClient_, thePLC->getIPAddress().c_str(), rackNb_, slotNb) :
+                                     Cli_Connect(recvClient_));
+
+            if (err == 0)
             {
-            	LOG(DEBUG) << "SNAP7 connection (channel-2) failed on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb << "/" << slotNb <<". SNAP7[" << err << "]: " << getSNAP7ErrorMessage(err);
-            	break;
+              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);
+                continue;
+              }
+
+              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 connect (channel-2) successful on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb << "/" << slotNb;
-            return true;
+            LOG(DEBUG) << "SNAP7 connection (channel-1) failed on PLC/rack/slot: " << thePLC->getName() << "/" << rackNb_ << "/" << slotNb <<". SNAP7[" << err << "]: " << getSNAP7ErrorMessage(err);
         }
-	    return false;
+        return (ret);
 	}
 
 
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 6e156f7..9ff8ba4 100644
--- a/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.h
+++ b/silecs-communication-cpp/src/silecs-communication/interface/communication/SNAP7Connection.h
@@ -55,6 +55,9 @@ namespace Silecs
 		bool open(PLC* thePLC);
 		bool close(PLC* thePLC);
 
+        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);
 	};
 
-- 
GitLab