A Lightweight Ethernet/IP API written to interface with Rockwell ControlLogix/CompactLogix Controllers.
A simple and lightweight node based API for interfacing with Rockwell Control/CompactLogix PLCs.
latest version of NodeJS
Install with npm
npm install ethernet-ip --save
How the heck does this thing work anyway? Great question!
const { Controller } = require("ethernet-ip");const PLC = new Controller();
// Controller.connect(IP_ADDR[, SLOT]) // NOTE: SLOT = 0 (default) - 0 if CompactLogix PLC.connect("192.168.1.1", 0).then(() => { console.log(PLC.properties); });
Controller.properties Object
javascript { name: String, // eg "1756-L83E/B" serial_number: Number, slot: Number, time: Date, // last read controller WallClock datetime path: Buffer, version: String, // eg "30.11" status: Number, faulted: Boolean, // will be true if any of the below are true minorRecoverableFault: Boolean, minorUnrecoverableFault: Boolean, majorRecoverableFault: Boolean, majorUnrecoverableFault: Boolean, io_faulted: Boolean }
NOTE
Controller.prototype.readWallClockand
Controller.prototype.writeWallClockare experimental features and may not be available on all controllers. 1756-L8 ControlLogix Controllers are currently the only PLCs supporting these features.
Sync Controller WallClock to PC Datetime
const { Controller } = require("ethernet-ip");const PLC = new Controller();
PLC.connect("192.168.1.1", 0).then(async () => { // Accepts a JS Date Type // Controller.writeWallClock([Date]) await PLC.writeWallClock(); // Defaults to 'new Date()' });
Set Controller WallClock to a Specific Date
const { Controller } = require("ethernet-ip");const PLC = new Controller();
PLC.connect("192.168.1.1", 0).then(async () => { const partyLikeIts1999 = new Date('December 17, 1999 03:24:00'); await PLC.writeWallClock(partyLikeIts1999); // Pass a custom Datetime });
NOTE: Currently, the
TagClass only supports Atomic datatypes (SINT, INT, DINT, REAL, BOOL). Not to worry, support for STRING, ARRAY, and UDTs are in the plans and coming soon! =]
Reading Tags
Individually... ```javascript const { Controller, Tag } = require("ethernet-ip");
const PLC = new Controller();
// Create Tag Instances const fooTag = new Tag("contTag"); // Controller Scope Tag const barTag = new Tag("progTag", "prog"); // Program Scope Tag in PLC Program "prog"
PLC.connect("192.168.1.1", 0).then(async () => { await PLC.readTag(fooTag); await PLC.readTag(barTag);
console.log(fooTag.value); console.log(barTag.value);
}); ```
Additional Tag Name Examples ...
javascript const fooTag = new Tag("Program:prog.progTag"); // Alternative Syntax for Program Scope Tag in PLC Program "prog" const barTag = new Tag("arrayTag[0]"); // Array Element const bazTag = new Tag("arrayTag[0,1,2]"); // Multi Dim Array Element const quxTag = new Tag("integerTag.0"); // SINT, INT, or DINT Bit const quuxTag = new Tag("udtTag.Member1"); // UDT Tag Atomic Member const quuzTag = new Tag("boolArray[0]", null, BIT_STRING); // bool array tag MUST have the data type "BIT_STRING" passed in
Reading Tags as a
Group... ```javascript const { Controller, Tag, TagGroup } = require("ethernet-ip");
const PLC = new Controller(); const group = new TagGroup();
// Add some tags to group group.add(new Tag("contTag")); // Controller Scope Tag group.add(new Tag("progTag", "prog")); // Program Scope Tag in PLC Program "prog"
PLC.connect("192.168.1.1", 0).then(async () => { await PLC.readTagGroup(group);
// log the values to the console group.forEach(tag => { console.log(tag.value); });
}); ```
NOTE: You MUST read the tags first or manually provide a valid CIP datatype. The following examples are taking the latter approach.
Writing Tags
Individually... ```javascript const { Controller, Tag, EthernetIP } = require("ethernet-ip"); const { DINT, BOOL } = EthernetIP.CIP.DataTypes.Types;
const PLC = new Controller();
// Create Tag Instances const fooTag = new Tag("contTag", null, DINT); // Controller Scope Tag const barTag = new Tag("progTag", "prog", BOOL); // Program Scope Tag in PLC Program "prog"
PLC.connect("192.168.1.1", 0).then(async () => {
// First way to write a new value fooTag.value = 75; await PLC.writeTag(fooTag);// Second way to write a new value await PLC.writeTag(barTag, true);
console.log(fooTag.value); console.log(barTag.value);
}); ```
Writing Tags as a
Group... ```javascript const { Controller, Tag, TagGroup, EthernetIP } = require("ethernet-ip"); const { DINT, BOOL } = EthernetIP.CIP.DataTypes.Types;
const PLC = new Controller(); const group = new TagGroup();
// Create Tag Instances const fooTag = new Tag("contTag", null, DINT); // Controller Scope Tag const barTag = new Tag("progTag", "prog", BOOL); // Program Scope Tag in PLC Program "prog"
group.add(fooTag); // Controller Scope Tag group.add(barTag); // Program Scope Tag in PLC Program "prog"
PLC.connect("192.168.1.1", 0).then(async () => { // Set new values fooTag.value = 75; barTag.value = true;
// Will only write tags whose Tag.controller_tag !== Tag.value await PLC.writeTagGroup(group);group.forEach(tag => { console.log(tag.value); });
}); ```
const { Controller, Tag } = require("ethernet-ip");const PLC = new Controller();
// Add some tags to group PLC.subscribe(new Tag("contTag")); // Controller Scope Tag PLC.subscribe(new Tag("progTag", "prog")); // Program Scope Tag in PLC Program "prog"
PLC.connect("192.168.1.1", 0).then(() => { // Set Scan Rate of Subscription Group to 50 ms (defaults to 200 ms) PLC.scan_rate = 50;
// Begin Scanning PLC.scan();
});
// Catch the Tag "Changed" and "Initialized" Events PLC.forEach(tag => { // Called on the First Successful Read from the Controller tag.on("Initialized", tag => { console.log("Initialized", tag.value); });
// Called if Tag.controller_value changes tag.on("Changed", (tag, oldValue) => { console.log("Changed:", tag.value); });
});
const { Controller, Tag } = require("ethernet-ip");// Intantiate Controller const PLC = new Controller();
// Subscribe to Tags PLC.subscribe(new Tag("TEST_TAG");); PLC.subscribe(new Tag("TEST", "Prog");); PLC.subscribe(new Tag("TEST_REAL", "Prog");); PLC.subscribe(new Tag("TEST_BOOL", "Prog"););
// Connect to PLC at IP, SLOT PLC.connect("10.1.60.205", 5).then(() => { const { name } = PLC.properties;
// Log Connected to Console console.log(`\n\nConnected to PLC ${name}...\n`); // Begin Scanning Subscription Group PLC.scan();
});
// Initialize Event Handlers PLC.forEach(tag => { tag.on("Changed", (tag, lastValue) => { console.log(
${tag.name} changed from ${lastValue} -> ${tag.value}
); }); })
Wanna become a contributor? Here's how!
This project is licensed under the MIT License - see the LICENCE file for details