- Reinstall jest dev dependency to fix security issue https://npmjs.com/advisories/1488
- Publishing again for release on github
- Added keywords to package.json
- Published
- CIPAttribute.Get(instance) instance parameter sets to zero if instance is null/undefined and attribute is instanceof CIPClassAttribute
- Added encoding support for internal CIP data type TRANSFORM
- Added CIPAttribute.Get() as a helper method for creating a GetAttributeSingle service CIPRequest
/** * Creates a GetAttributeSingle service CIPRequest for retrieving the device * type of Identity object instance 1 */ const request = CIP.Core.Objects.Identity.InstanceAttribute.DeviceType.Get(1);
- Improved CIPRequest and CIPMultiServiceRequest
- A CIPRequest can be specified as the data handler for another CIPRequest (see ConnectionManager's UnconnectedSend method)
- CIPMultiServiceRequest (CIPRequest.Multi) now works
- Here is an example of two requests inside of a multi service request inside of an unconnected send
const { TCP, CIP } = require('node-drivers'); const tcpLayer = new TCP('1.2.3.4'); const cipLayer = new CIP(tcpLayer); /** Create an Unconnected Send request */ const request = CIP.Core.Objects.ConnectionManager.UnconnectedSend( /** multi service request */ new CIP.Core.Request.Multi([ /** two different GetAttributeSingle requests */ CIP.Core.Objects.MessageRouter.InstanceAttribute.ObjectList.Get(1), CIP.Core.Objects.Port.InstanceAttribute.Name.Get(1) ]), /** routing out of port 1 to address 0 */ CIP.Core.EPath.Encode(true, [ new CIP.Core.EPath.Segments.Port(1, 0) ]) ); /** Use the CIP layer to send the unconnected message */ const res = await cipLayer.sendRequest(false, request); /** res.value is an array of response objects (2 responses in this case) */ console.log(res.value); await tcpLayer.close();
- Fixed CIP Layer sendRequest not propagating errors
- The Layers object exported by the package has been removed.
/** Before */ const { TCP } = require('node-drivers').Layers; /** After */ const { TCP } = require('node-drivers');
- EIP layer has been moved under CIP
/** Before */ const EIPLayer = require('node-drivers').EIP; /** After */ const EIPLayer = require('node-drivers').CIP.EIP;
- EIP layer is now automatically inserted in the layer stack by CIP layers when the lower layer is TCP or UDP.
const { TCP, CIP } = require('node-drivers'); /** If access to EIP layer is necessary: */ const tcpLayer = new TCP('1.2.3.4'); const eipLayer = new CIP.EIP(tcpLayer); const logix = new CIP.Logix5000(eipLayer); /** If access to EIP layer is not necessary: */ const tcpLayer = new TCP('1.2.3.4'); const logix = new CIP.Logix5000(tcpLayer);
- CIP.PCCC and CIP.Modbus layers have been removed. CIP layer should now be directly used when forwarding PCCC embedded in CIP. Modbus over CIP will come soon.
const { TCP, CIP, PCCC } = require('node-drivers'); /** Before */ const tcpLayer = new TCP('1.2.3.4'); const cipPCCCLayer = new CIP.PCCC(tcpLayer); // CIP.PCCC has been removed const pccc = new PCCC(cipPCCCLayer); /** After */ const tcpLayer = new TCP('1.2.3.4'); const cipLayer = new CIP(tcpLayer); // Use CIP layer directly const pcccLayer = new PCCC(cipLayer);
- Added CIPObject DecodeInstanceAttributesAll static method
- Overall improvement of CIP core and added external access
const CIPCore = require('node-drivers').CIP.Core;
- Fixed EIP ListIdentity response data decoding
- Fixed CIPRequest handling response data when length is 0
- EPath Port Segment now encodes the pad byte ensuring the pad byte is 0 and the buffer is large enough
- EPath DataType Segment fixed encodeSize for ARRAY and reference error when decoding abbreviated array
- EPath Data Segment finished
- Added unit tests for Data and DataType EPath segments
- Logix5000.readControllerAttributes() now throws descriptive error if attribute status is not successful
- Logix5000 fixed boolean decoding
- Logix5000 listTags now allows async iterator style as well as callback style
- async iterator style:
let i = 0; for await (const tag of logix.listTags()) { i++; console.log(i, tag); if (i >= 10) { break; } }
- callback style:
let i = 0; logix.listTags(function(tag) { if (tag != null) { i++; console.log(i, tag); return i < 10; // return true to continue listing tags } else { // tag is null so listing is finished } });
- Improved EIP Layer listIdentities timeout handling, it should be much faster to resolve
- CIP added encoding and decoding for ENGUNIT data type
- Logix5000 can read program symbols, returns an object with all scoped symbols
- Logix5000 can now read program scoped symbols
- Logix5000 can now determine size of single-dimension arrays and reads the entire array if elements is not specified (multidimensional array read support coming soon)
- Logix5000 added readTemplateClassAttributes
- UDP layer now receives default port 44818 from upper EIP layer if user or previous layer does not specify port
- CIP added decoding for data types LREAL, LWORD, and LTIME, STRINGN, STRINGI STRUCT (formal encoding), EPATH, ARRAY
- CIP added encoding for data types USINT, BYTE, LWORD, LREAL, STRING, SHORT_STRING, STRING2, EPATH, ARRAY, ABBREV_ARRAY, STRUCT
- CIP Connection Slot can now be a number, a string, or a buffer
- CIP Identity added Device Type Names
- CIP Connection/ConnectionManager now supports LargeForwardOpen (connection size greater than 511 bytes), automatically falls back to regular ForwardOpen if device does not support LargeForwardOpen
Logix5000.readTag()
now reads the entire array if the tag is a 1-dimensional array- It is still possible to only return one element or a slice of the array by specifying the
elements
argument and/or including the accessed element in the tagname. Here are some examples:- Return the first two elements
await logix.readTag('tagname', 2);
- Return the fourth element
await logix.readTag('tagname[3]');
- Return the second through the third element
await logix.readTag('tagname[1]', 2);
- Return the first two elements
- It is still possible to only return one element or a slice of the array by specifying the
- Layers can now specify default options and pass them to lower layers
- TCP layer now receives default port 44818 from upper EIP layer if user or previous layer does not specify port
- TCP layer now receives default port 502 from upper Modbus layer if user or previous layer does not specify port
- TCP layer's options argument can now just be a host string if an upper layer specifies a port in the default options (EIP and Modbus layer)
- Before:
const tcpLayer = new TCP({ host: '1.2.3.4', port: 44818 });
- After:
const tcpLayer = new TCP('1.2.3.4');
- Before:
- Fixed
PCCCLayer.typedWrite()
type/data parameter encoding PCCCLayer.typedRead()
addeditems
parameter, allows reading multiple items- Examples:
await plc5.typedRead('N7:0', 6); // Read the first 6 elements from integer file 7 await plc5.typedRead('F8:44', 20); // Read elements 44 through 63 from float file 8
- CIP added encoding and decoding for 8 byte integer (LINT) and unsigned integer (ULINT)
Logix5000.readTagAttributesAll()
added ArrayDimensionLengths- Logix5000 fixed error descriptions
- Logix5000 CAN NOW READ STRUCTURES 🔥
- TCP layer automatically handles reconnects
- Logix5000 listTags now accepts a scope (e.g. Program:SymbolName)
- Logix5000 added data types Program, Map, Routine, Task, Cxn
- Removed
Logix5000.readTagFragmented()
, it is now called automatically when needed - Added
PCCCLayer.echo()
- CIP ConnectionManager can now send unconnected messages - API still a work in progress
- Logix5000.readControllerAttributes
- reads the 0xAC class instance attributes in the controller
- Use to determine when the tags list and/or structure information has changed
- Logix5000.readTagAttributesList
- Logix5000.readTagAttributesAll
- Logix5000.readTag now accepts a tag name string, a symbol instance id, or a tag object for the tag argument
- Logix5000 error description handling
- Modbus layer - one layer for all Modbus frame formats
- TCP, RTU (future), and ASCII (future)
- ModbusTCP layer has been removed, use Modbus layer instead
- Logix5000.listTags
- now returns an async iterator
- structure tags now include template information
- src structure has been simplified
- Added CIP.Connection disconnect timeout of 10000 milliseconds
- CIP Decode returns true or false for boolean data type
- Layer contextCallback added timeout parameter
- CIP.Logix5000 listTags added options parameter, allowed fields:
- timeout - timeout in milliseconds, will return tags instead of timeout error if at least one response received with tags (default 10000)
- CIP.Logix5000 allows reading multiple elements from tags
- e.g. logix.readTag('tagname', 2)
- resolves an array of values if number is greater than 1
- CIP.Logix5000 no longer requires including CIP.Connection as a lower layer.
- CIP.Connection only connects if needed
- e.g. getting all attributes of identity object does not require a connection