plcpeople / nodeS7

Node.JS library for communication to Siemens S7 PLCs
MIT License
365 stars 122 forks source link

nodeS7

NodeS7 is a library that allows communication to S7-300/400/1200/1500 PLCs using the Siemens S7 Ethernet protocol RFC1006.

This software is not affiliated with Siemens in any way, nor am I. S7-300, S7-400, S7-1200 and S7-1500 are trademarks of Siemens AG.

WARNING

Fully test everything you do. In situations where writing to a random area of memory within the PLC could cost you money, back up your data and test this really well. If this could injure someone or worse, consider other software.

Installation

Using npm:

Using yarn:

Optimization

PLC Support

VFD Support

Credit to the S7 Wireshark dissector plugin for help understanding why things were not working. (http://sourceforge.net/projects/s7commwireshark/)

Examples

var nodes7 = require('nodes7'); // This is the package name, if the repository is cloned you may need to require 'nodeS7' with uppercase S
var conn = new nodes7;
var doneReading = false;
var doneWriting = false;

var variables = {
      TEST1: 'MR4',          // Memory real at MD4
      TEST2: 'M32.2',        // Bit at M32.2
      TEST3: 'M20.0',        // Bit at M20.0
      TEST4: 'DB1,REAL0.20', // Array of 20 values in DB1
      TEST5: 'DB1,REAL4',    // Single real value
      TEST6: 'DB1,REAL8',    // Another single real value
      TEST7: 'DB1,INT12.2',  // Two integer value array
      TEST8: 'DB1,LREAL4',   // Single 8-byte real value
      TEST9: 'DB1,X14.0',    // Single bit in a data block
      TEST10: 'DB1,X14.0.8'  // Array of 8 bits in a data block
};

conn.initiateConnection({ port: 102, host: '192.168.0.2', rack: 0, slot: 1, debug: false }, connected); // slot 2 for 300/400, slot 1 for 1200/1500, change debug to true to get more info
// conn.initiateConnection({port: 102, host: '192.168.0.2', localTSAP: 0x0100, remoteTSAP: 0x0200, timeout: 8000, doNotOptimize: true}, connected);
// local and remote TSAP can also be directly specified instead. The timeout option specifies the TCP timeout.

function connected(err) {
  if (typeof(err) !== "undefined") {
    // We have an error. Maybe the PLC is not reachable.
    console.log(err);
    process.exit();
  }
  conn.setTranslationCB(function(tag) { return variables[tag]; }); // This sets the "translation" to allow us to work with object names
  conn.addItems(['TEST1', 'TEST4']);
  conn.addItems('TEST6');
  // conn.removeItems(['TEST2', 'TEST3']); // We could do this.
  // conn.writeItems(['TEST5', 'TEST6'], [ 867.5309, 9 ], valuesWritten); // You can write an array of items as well.
  // conn.writeItems('TEST7', [666, 777], valuesWritten); // You can write a single array item too.
  conn.writeItems('TEST3', true, valuesWritten); // This writes a single boolean item (one bit) to true
  conn.readAllItems(valuesReady);
}

function valuesReady(anythingBad, values) {
  if (anythingBad) { console.log("SOMETHING WENT WRONG READING VALUES!!!!"); }
  console.log(values);
  doneReading = true;
  if (doneWriting) { process.exit(); }
}

function valuesWritten(anythingBad) {
  if (anythingBad) { console.log("SOMETHING WENT WRONG WRITING VALUES!!!!"); }
  console.log("Done writing.");
  doneWriting = true;
  if (doneReading) { process.exit(); }
}

API

nodes7.initiateConnection(options, callback)

Description

Connects to a PLC.

Arguments

Options

Property type default
rack number 0
slot number 2
port number 102
host string 192.168.8.106
timeout number 5000
localTSAP hex undefined
remoteTSAP hex undefined

callback(err)

err
err is either an error object, or undefined on successful connection.

nodes7.dropConnection(callback)

Description

Disconnects from a PLC. This simply terminates the TCP connection.

Arguments

callback()

The callback is called upon completion of the close.

nodes7.setTranslationCB(translator)

Description

Sets a callback for name - address translation.

This is optional - you can choose to use "addItem" etc with absolute addresses.

If you use it, translator should be a function that takes a string as an argument, and returns a string in the following format: <data block number.><memory area><data type><byte offset><.array length>

Examples:

The DT type is the well-known DATE_AND_TIME type of S7-300/400 PLCs, a 8-byte-wide field with BCD-encoded parts

The DTZ type is the same as the DT, but it expects that the timestamp is in UTC in the PLC (usually NOT the case)

The DTL type is the one seen on newer S7-1200/1500 PLCs, is 12-byte long and encodes the timestamp differently than the older DATE_AND_TIME

The DTLZ type is also the same as the DTL, but expecting the timestamp in UTC in the PLC

In the example above, an object is declared and the translator references that object. It could just as reference a file or database. In any case, it allows cleaner Javascript code to be written that refers to a name instead of an absolute address.

nodes7.addItems(items)

Description

Adds items to the internal read polling list.

Arguments

items can be a string or an array of strings.

If items includes the value _COMMERR it will return current communication status.

nodes7.removeItems(items)

Description

Removes items to the internal read polling list.

Arguments

items can be a string or an array of strings.

If items is not defined then all items are removed.

nodes7.writeItems(items, values, callback)

Description

Writes items to the PLC using the corresponding values and calls callback when done.

You should monitor the return value - if it is non-zero, the write will not be processed as there is already one it progress, and the callback will not be called.

Arguments

items can be a string or an array of strings.

If items is a single string, values should then be a single item.

If items is an array of strings, values must also be an array of values.

callback(err)

err
a boolean indicating if ANY of the items have "bad quality".

nodes7.readAllItems(callback)

Description

Reads the internal polling list and calls callback when done.

Arguments

callback(err, values)

err
a boolean indicating if ANY of the items have "bad quality".
values
an object containing the values being read as keys and their value (from the PLC) as the value.