Skip to content

Commit

Permalink
Added .Close() to close the session with the PLC. Scripts should use …
Browse files Browse the repository at this point in the history
…this now to properly close the session. See the updated README
  • Loading branch information
dmroeder committed Oct 27, 2016
1 parent 2651517 commit b6c222c
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 10 deletions.
6 changes: 4 additions & 2 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,16 @@ USAGE - Python 2.7.11
ex: stuff = test.Discover()
print stuff(1).IPAddress # prints the first devices IP Address


5) Close the connection with test.Close()

So a complete script to read a tag would look like this:

from eip import PLC
test = PLC()
test.IPAddress = "192.168.1.64"
value = test.Read("MyTimer.ACC")
print value
test.Close()



Expand Down Expand Up @@ -84,4 +86,4 @@ In order to perform a typical read/write, the data type needs to be known, or
data type. This helps us in two ways: First, the user won't need to specify
the data type. Second, we can keep track of this information so the next
time the particular tag is called, we already know it's type so we can just
do the normal read/write (0x4C/0x4D/0x4E).
do the normal read/write (0x4C/0x4D/0x4E).
16 changes: 10 additions & 6 deletions changelog
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
10/27/16
-Added .Close() to close the session with the PLC. Whenever a script is done
.Close() should be called.

10/26/16
Added _getBytes() for sending/receiving data. Should handle failure better
Rewrote _connect() to handle disconnect/reconnects better
-Added _getBytes() for sending/receiving data. Should handle failure better
-Rewrote _connect() to handle disconnect/reconnects better

08/17/16
Fixed tagIOI not dealing with greater than 4 byte tag index
-Fixed tagIOI not dealing with greater than 4 byte tag index

08/05/16
Fixed derp with calling _getTagList
-Fixed derp with calling _getTagList

07/29/16
Fixed writing to boolean array
-Fixed writing to boolean array

07/27/16
-Fixed defaulting to element zero when writing to an array value
Expand Down Expand Up @@ -180,4 +184,4 @@
03/14/2015
-Removed duplicate CIPTagReadRequest function (from testing)
-Initial commit


79 changes: 77 additions & 2 deletions eip.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ def Discover(self):
'''
return _discover()

def Close(self):
'''
Close the connection to the PLC
'''
return _closeConnection(self)

class LGXTag():

Expand Down Expand Up @@ -369,6 +374,19 @@ def _connect(self):
print "Forward Open Failed"
return

def _closeConnection(self):
'''
Close the connection to the PLC (forward close, unregister session)
'''
closePacket = _buildForwardClosePacket(self)
unregPacket = _buildUnregisterSession(self)
retData = _getBytes(self, closePacket)
retData = _getBytes(self, unregPacket)
try:
self.Socket.close()
except:
pass

def _getBytes(self, data):
'''
Sends data and gets the return data
Expand All @@ -382,11 +400,9 @@ def _getBytes(self, data):
return None
except socket.gaierror, e:
self.SocketConnected = False
print e
return None
except IOError, e:
self.SocketConnected = False
print e
return None

def _buildRegisterSession(self):
Expand All @@ -413,6 +429,22 @@ def _buildRegisterSession(self):
EIPProtocolVersion,
EIPOptionFlag)

def _buildUnregisterSession(self):
EIPCommand = 0x66 #(H)
EIPLength = 0x00 #(H)
EIPSessionHandle = self.SessionHandle #(I)
EIPStatus = 0x0000 #(I)
EIPContext = self.Context #(Q)
EIPOptions = 0x0000 #(I)

return pack('<HHIIQI',
EIPCommand,
EIPLength,
EIPSessionHandle,
EIPStatus,
EIPContext,
EIPOptions)

def _buildForwardOpenPacket(self):
'''
Assemble the forward open packet
Expand All @@ -421,6 +453,14 @@ def _buildForwardOpenPacket(self):
rrDataHeader = _buildEIPSendRRDataHeader(self, len(forwardOpen))
return rrDataHeader+forwardOpen

def _buildForwardClosePacket(self):
'''
Assemble the forward close packet
'''
forwardClose = _buildForwardClose(self)
rrDataHeader = _buildEIPSendRRDataHeader(self, len(forwardClose))
return rrDataHeader + forwardClose

def _buildCIPForwardOpen(self):
'''
Forward Open happens after a connection is made,
Expand Down Expand Up @@ -488,6 +528,41 @@ def _buildCIPForwardOpen(self):
CIPConnectionPathSize,
CIPConnectionPath[0],CIPConnectionPath[1],CIPConnectionPath[2],CIPConnectionPath[3],
CIPConnectionPath[4],CIPConnectionPath[5])

def _buildForwardClose(self):
CIPService = 0x4E #(B) CIP OpenForward Vol 3 (3-5.5.2)(3-5.5)
CIPPathSize = 0x02 #(B) Request Path zize (2-4.1)
CIPClassType = 0x20 #(B) Segment type (C-1.1)(C-1.4)(C-1.4.2)
#[Logical Segment][Class ID][8 bit addressing]
CIPClass = 0x06 #(B) Connection Manager Object (3-5)
CIPInstanceType = 0x24 #(B) Instance type (C-1.1)

CIPInstance = 0x01 #(B) Instance
CIPPriority = 0x0A #(B) Timeout info (3-5.5.1.3)(3-5.5.1.2)
CIPTimeoutTicks = 0x0e #(B) Timeout Info (3-5.5.1.3)
CIPConnectionSerialNumber = self.SerialNumber #(H) Serial number for THIS connection (3-5.5.1.4)
CIPVendorID = self.VendorID #(H)
CIPOriginatorSerialNumber = self.OriginatorSerialNumber #(I)
CIPConnectionPathSize = 0x03 #(B) (3-5.5.1.9)
CIPReserved = 0x00 #(B)
CIPConnectionPath = (0x01,self.ProcessorSlot,0x20,0x02,0x24,0x01) #(6B) Compressed / Encoded Path (C-1.3)(Fig C-1.2)

return pack('<BBBBBBBBHHIBB6B', CIPService,
CIPPathSize,
CIPClassType,
CIPClass,
CIPInstanceType,
CIPInstance,
CIPPriority,
CIPTimeoutTicks,
CIPConnectionSerialNumber,
CIPVendorID,
CIPOriginatorSerialNumber,
CIPConnectionPathSize,
CIPReserved,
CIPConnectionPath[0], CIPConnectionPath[1],
CIPConnectionPath[2], CIPConnectionPath[3],
CIPConnectionPath[4], CIPConnectionPath[5])

def _buildEIPSendRRDataHeader(self, frameLen):
EIPCommand = 0x6F #(H)EIP SendRRData (Vol2 2-4.7)
Expand Down

0 comments on commit b6c222c

Please sign in to comment.