Nodejs package to handle PLC as Micro800 of Allen Bradley or Logix
-
Promise response with bluebird
-
Manager multiple connections to write/read tags using pooling with generic-pool
-
Listener events as connect, connect_error, disconnect, closing, or found, found_error (discover function)
-
Ardunio mode: functions as digitalRead, digitalWrite, analogWrite, analogRead, digitalOutRead and analogOutRead
-
Autoclose EIP Socket session
-
Enable or disable identity on connect (ignoreIdentity param in connect function)
-
Support to write and read string or array
-
Support typescript
-
Support Micro800
npm install node-logix
or
yarn add node-logix
- EtherNet/IP
const PLC = require("node-logix").default;
const comm = new PLC("192.168.100.9");
comm.on("connect", () => {
console.log("PLC connected successful! ");
comm
.write("TEST_USINT", 127)
.then(() => {
return comm.read("TEST_USINT").then(console.log);
})
.catch(console.error);
});
comm.on("connect_error", e => {
console.log("Fail to connect PLC", e);
});
comm.on("disconnect", reason => {
console.log("PLC disconnected reason:", reason);
});
Find devices using dgram socket
const PLC = require("node-logix").default;
PLC.discover().then(devices => {
console.log("Devices:", devices);
});
comm
.digitalRead(0)
.then(result => {
console.timeEnd("reading digital");
console.log("value of:", result.valueOf(), "tagName:", result.tagName);
})
.catch(console.error);
[0, 1, 2, 3, 4, 5, 6].forEach(p => {
comm
.digitalWrite(p, false)
.then(console.log)
.catch(e => console.error("error write", e));
});
PLC.defaultOptions = {
allowHalfOpen: true, // Socket option nodejs, keep open TCP socket
Micro800: false, // use path for Micro800
port: 44818, // default port EIP
connectTimeout: 3000,
arduinoMode: true, // Enable Arduino functions only Micro800
pool: { // options generic-pool
min: 0,
max: 3,
Promise : Bluebird, //bluebird
priorityRange: 2,
fifo: false,
testOnBorrow: true,
evictionRunIntervalMillis: 17000,
idleTimeoutMillis: 30000
}
- ArduinoMode only working with Micro800 enable, to working with other PLC, yout must be create custom pinMapping JSON and replacePin function:
comm.pinMapping = {
digital: {
output: "_IO_EM_DO_{dd}",
input: "_IO_EM_DI_{dd}"
},
analog: {
input: "_IO_EM_AI_{dd}",
output: "_IO_EM_AO_{dd}"
}
};
/**
* @description replace pin mapping
* @param {String} str
* @param {Number} pin
* @param {String}
*/
function _replacePin(str = "", pin) {
if (typeof str !== "string")
throw new TypeError("Pin must be a string not a " + typeof str);
if (typeof pin === "string" && !/\d{1,}/.test(pin))
throw new TypeError("Pin must has number to assing pin value: " + pin);
const match = str.match(/{(d+)}/);
if (match === null)
throw new PinMappingError(`Replace: ${str} no match with {d} or {dd}`);
if (match.index > 0) {
return str.replace(match[0], String(pin).padStart(match[1].length, "0"));
}
return str;
}
Connection size:
-
Packets have a ~500 byte limit, so you have to be cautions about not exceeding that or the read will fail. It's a little difficult to predict how many bytes your reads will take up becuase the send packet will depend on the length of the tag name and the reply will depened on the data type. Strings are a lot longer than DINT's for example.
-
Micro800 has CIP protocol Limited, check examples to check work functions
- Unit testing
This project is licensed under the MIT License - see the LICENCE file for details