07/21/18 -Fixed bools that are part of an array with MultiRead. Ex MyBool[0] 07/18/18 -Fixed reading bits of a word with MultiRead. Ex: DintTag.0 06/03/18 -Fixed issues handling CIP error codes -Fixed issue when mixing Read with MultiRead 04/08/18 -Increased default socket timeout 10/23/17 -Raise error for unsupported features 10/06/17 -Added Micro8xx support -Cleaned up formatting of lgxDevice.py 10/05/17 -Added array writing -Forward Open/Close cleanup 09/29/17 -Rewrote reply parser to handle bit/bool arrays 06/06/17 -Specify max timeout when discovering devices 06/04/17 -Fixed multiread not dealing with strings properly 03/21/17 -Fixed GetTagList() appending program scoped tags 03/17/17 -Fixed GetTagList() appending every time it is called 02/17/17 -Updated InitialRead usage -Found a few more formatting issues 02/12/17 -Cleaned up _connect() and it's usage 02/11/17 -Fixed CIP type for LINT, changed to signed -Cleaned up some formatting issues -Fixed crash on a read/write after a multi-packet reply -Modified InitialRead() to raise exception if tag doesn't exist 02/06/17 -Use a different attribute in GetPLCTime() -Added SetPLCTime() to set the PLC clock 11/23/16 -GetTagList() now includes program scoped tags 11/21/16 -Rewrote GetTagList() to be more efficient, uses connected send 11/16/16 -Fixed crash if GetTagList() was called twice 10/29/16 -Fixed derp with _connect in _multiRead() 10/27/16 -Added .Close() to close the session with the PLC. Whenever a script is done .Close() should be called. -Added __exit__() so PLC can be used in a with statement 10/26/16 -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 08/05/16 -Fixed derp with calling _getTagList 07/29/16 -Fixed writing to boolean array 07/27/16 -Fixed defaulting to element zero when writing to an array value 07/09/16 -Added CIP error messages, fixed looking at wrong byte for error -Fixed single bool from array write 07/07/16 -.discover() returns .IPAddress instead of .Address -Moved some code from _parseIdentityResponse() to lgxDevice.py to simplify function -Fixed issue with some devices failing to parse -Better filtering discovered devices 06/15/16 -Added GetTagList() to retreive the controller scope tags 06/14/16 -Added Discover() to query all of the Ethernet I/P devices on the network. 06/09/16 -Added multi-read function back in, also GetPLCTime() -Fixed writing strings 06/08/16 -Fixed multi-dim read's, array reads. Write functions now working 06/07/16 -Rewrite eip.py. Trying to make it easier to use, only Read functions work for now 04/07/16 -Modified identify.py to get rid of the functions for the lists 03/04/16 -Fixed issue reading array only returning first element 02/25/16 -more mods to identify.py, made it more pythonic with JordanCClark's suggestions -try without binding if looping through ipv4 addreses doesn't return anything 02/22/16 -identify.py now sends packet out each network adapter 12/11/15 -Fixed incorrect vendorID's in identify.py -Filter out garbage from GetTagList -Added MultiRead() function 11/28/15 -Renamed SetIPAddress to IPAddress and SetProcessorSlot to ProcessorSlot -Updated README with identify.py info 11/27/15 -SequencCounter starts at 1, apparently L32E has problem with it starting at zero 11/23/15 -Added rolling context 10/15/15 -Pretty major rewrite of how we build the CIP request, more to come I'm sure 10/14/15 -DataType is retreived properly now (one byte) 10/09/15 -Reworked the Read function a bit 10/08/15 -Updated TagNameParser and InitialRead to store only base tag -Fixed read STRING array returning only the first string 10/07/15 -Initial reads minimum amount of data to get data type 10/06/15 -Fixed single bool array read derp, removed some old code -Reworked CIPDataTypes dict -Removed, obsolete functions -Context is no longer a string -Fixed STRING array reads 10/05/15 -Fixed multi dim write -Added write single array bool support 10/04/15 -Added multi dim read support 10/01/15 -A bunch of rework for reading/writing bit of a word -Cleaned up extra read when writing to tag 09/28/15 -Read single BOOL from array works now, reworked initial tag read -Fixed bit of a word reading, changed code for checking value of bit of a word 09/27/15 -Each unique tag read gets stored in a dictionary so we won't read it again when we do a write -Back to returning just value instead of tag type -Cleaned up write function with new dict changes, fixed issue with bit of word confusion -Cleaned some more commented functions 09/22/15 -Fixed large array read bug -Fixed LINT array reads -Added TagNameParser function 09/20/15 -Large array reads now sort of working 08/31/15 -Write bit of a word fixed (something wrong with bit 31) 08/27/2015 -Added ParsePacket to LGXTag which GetTagList uses -Read now returns LGXTag type -Write no longer requres providing data type -Fixed GetTagList when processor is not in slot 0 08/26/2015 -Added LINT read support -Added functino .GetPLCTime() -Fixed write reporting error when successful -Removed some white space 06/20/2015 -Removed duplicate _buildEIPSendRRDatHeader, renamed some stuff -Fixed TagName length, was grabbing extra data -Write now reports an error if it fails 06/17/15 -Created LGXTag object, GetTagList() now returns list of LGXTag -Modified read for string to accomodate custom string size data types -Renamed ReadStuffs/WriteStuffs to Read/Write, "STRUCT" data type renamed to "STRING" 06/15/2015 -GetTagList() is now working. Still could use some work though. 06/14/2015 -Rename some TagList functions, combined TagListMessage functions, still needs work 06/12/2015 -Added GetTagList function, needs some serious work though 04/07/2015 -Removed some old code (open connection) -OpenConnection is handled in Read/Write functions, must use .SetIPAddress("192.168.1.10") 03/23/2015 -Added ProcessorSlot. If not in slot 0, use .SetProcessorSlot(n) 03/22/2015 -Added check for connection in read/write functions, no longer crashes -Added change log 03/18/2015 -Removed buildCIPTagRead and Write requests (now one funtion) 03/17/2015 -Merged buildTagRead and Write Request into one common function called buildTagRequest -Cleaned up some code 03/16/2015 -Reworked CIPRequest to read complex data types (specific array elements and UDT's) -Added ability to read a single simple array element 03/14/2015 -Removed duplicate CIPTagReadRequest function (from testing) -Initial commit