{"id":15575156,"url":"https://github.com/cmseaton42/node-ethernet-ip","last_synced_at":"2025-04-04T06:09:25.194Z","repository":{"id":39788019,"uuid":"117992019","full_name":"cmseaton42/node-ethernet-ip","owner":"cmseaton42","description":"A Lightweight Ethernet/IP API written to interface with Rockwell ControlLogix/CompactLogix Controllers.","archived":false,"fork":false,"pushed_at":"2023-01-03T23:00:59.000Z","size":19877,"stargazers_count":264,"open_issues_count":56,"forks_count":106,"subscribers_count":45,"default_branch":"master","last_synced_at":"2024-10-13T09:15:38.450Z","etag":null,"topics":["allen","allen-bradley","automation","bradley","communication","communication-protocol","datatype","ethernet","ethernet-ip","ethernet-protocol","javascript","node-ethernet","nodejs","plc","rockwell"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cmseaton42.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-18T14:16:55.000Z","updated_at":"2024-10-12T05:28:49.000Z","dependencies_parsed_at":"2023-02-01T12:32:06.107Z","dependency_job_id":null,"html_url":"https://github.com/cmseaton42/node-ethernet-ip","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmseaton42%2Fnode-ethernet-ip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmseaton42%2Fnode-ethernet-ip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmseaton42%2Fnode-ethernet-ip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmseaton42%2Fnode-ethernet-ip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cmseaton42","download_url":"https://codeload.github.com/cmseaton42/node-ethernet-ip/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247128752,"owners_count":20888235,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["allen","allen-bradley","automation","bradley","communication","communication-protocol","datatype","ethernet","ethernet-ip","ethernet-protocol","javascript","node-ethernet","nodejs","plc","rockwell"],"created_at":"2024-10-02T18:22:58.013Z","updated_at":"2025-04-04T06:09:25.175Z","avatar_url":"https://github.com/cmseaton42.png","language":"JavaScript","readme":"\u003cp align=\"center\"\u003e\u003cimg width=\"280\" src=\"https://i.imgur.com/HNxhZox.png\" alt=\"Vue logo\"\u003e\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cp\u003e\u003ca href=\"https://www.npmjs.com/package/ethernet-ip\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/ethernet-ip.svg?style=flat-square\" alt=\"npm\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://gitter.im/node-ethernet-ip/Lobby\"\u003e\u003cimg src=\"https://img.shields.io/gitter/room/node-ethernet-ip/nw.js.svg?style=flat-square\" alt=\"Gitter\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/cmseaton42/node-ethernet-ip/blob/master/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/cmseaton42/node-ethernet-ip.svg?style=flat-square\" alt=\"license\" /\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/travis/cmseaton42/node-ethernet-ip.svg?style=flat-square\" alt=\"Travis\" /\u003e\n  \u003cimg src=\"https://img.shields.io/coveralls/github/cmseaton42/node-ethernet-ip.svg?style=flat-square\" alt=\"Coveralls github\" /\u003e\n  \u003cimg src=\"https://snyk.io/test/github/cmseaton42/node-ethernet-ip/badge.svg?targetFile=package.json\" alt=\"Known Vulnerabilities\" data-canonical-src=\"https://snyk.io/test/github/cmseaton42/node-ethernet-ip?targetFile=package.json\" style=\"max-width:100%;\"\u003e\n  \u003ca href=\"https://github.com/cmseaton42/node-ethernet-ip\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/cmseaton42/node-ethernet-ip.svg?\u0026amp;style=social\u0026amp;logo=github\u0026amp;label=Stars\" alt=\"GitHub stars\" /\u003e\u003c/a\u003e\u003c/p\u003e\n\u003c/div\u003e\n\n\n# Node Ethernet/IP\n\nA simple and lightweight node based API for interfacing with Rockwell Control/CompactLogix PLCs.\n\n## Prerequisites\n\nlatest version of [NodeJS](https://nodejs.org/en/)\n\n## Getting Started\n\nInstall with npm\n\n```\nnpm install ethernet-ip --save\n```\n## The API\n\nHow the heck does this thing work anyway? Great question!\n\n### The Basics\n\n#### Getting Connected\n\n```javascript\nconst { Controller } = require(\"ethernet-ip\");\n\nconst PLC = new Controller();\n\n// Controller.connect(IP_ADDR[, SLOT])\n// NOTE: SLOT = 0 (default) - 0 if CompactLogix\nPLC.connect(\"192.168.1.1\", 0).then(() =\u003e {\n    console.log(PLC.properties);\n});\n```\n\nController.properties Object\n```javascript\n {\n    name: String, // eg \"1756-L83E/B\"\n    serial_number: Number, \n    slot: Number,\n    time: Date, // last read controller WallClock datetime\n    path: Buffer,\n    version: String, // eg \"30.11\"\n    status: Number,\n    faulted: Boolean,  // will be true if any of the below are true\n    minorRecoverableFault: Boolean,\n    minorUnrecoverableFault: Boolean,\n    majorRecoverableFault: Boolean,\n    majorUnrecoverableFault: Boolean,\n    io_faulted: Boolean\n}\n```\n\n#### Set the Clock of the Controller\n\n**NOTE** `Controller.prototype.readWallClock` and `Controller.prototype.writeWallClock` are experimental features and may not be available on all controllers. 1756-L8 ControlLogix Controllers are currently the only PLCs supporting these features.\n\nSync Controller WallClock to PC Datetime\n\n```javascript\nconst { Controller } = require(\"ethernet-ip\");\n\nconst PLC = new Controller();\n\nPLC.connect(\"192.168.1.1\", 0).then(async () =\u003e {\n    // Accepts a JS Date Type\n    // Controller.writeWallClock([Date])\n    await PLC.writeWallClock(); // Defaults to 'new Date()'\n});\n```\n\nSet Controller WallClock to a Specific Date\n\n```javascript\nconst { Controller } = require(\"ethernet-ip\");\n\nconst PLC = new Controller();\n\nPLC.connect(\"192.168.1.1\", 0).then(async () =\u003e {\n    const partyLikeIts1999 = new Date('December 17, 1999 03:24:00');\n    await PLC.writeWallClock(partyLikeIts1999); // Pass a custom Datetime\n});\n```\n\n#### Reading Tags\n\n**NOTE:** Currently, the `Tag` Class 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! =]\n\nReading Tags `Individually`...\n```javascript\nconst { Controller, Tag } = require(\"ethernet-ip\");\n\nconst PLC = new Controller();\n\n// Create Tag Instances\nconst fooTag = new Tag(\"contTag\"); // Controller Scope Tag\nconst barTag = new Tag(\"progTag\", \"prog\"); // Program Scope Tag in PLC Program \"prog\"\n\nPLC.connect(\"192.168.1.1\", 0).then(async () =\u003e {\n    await PLC.readTag(fooTag);\n    await PLC.readTag(barTag);\n\n    console.log(fooTag.value);\n    console.log(barTag.value);\n});\n```\n\nAdditional Tag Name Examples ...\n```javascript\nconst fooTag = new Tag(\"Program:prog.progTag\"); // Alternative Syntax for Program Scope Tag in PLC Program \"prog\"\nconst barTag = new Tag(\"arrayTag[0]\"); // Array Element\nconst bazTag = new Tag(\"arrayTag[0,1,2]\"); // Multi Dim Array Element\nconst quxTag = new Tag(\"integerTag.0\"); // SINT, INT, or DINT Bit\nconst quuxTag = new Tag(\"udtTag.Member1\"); // UDT Tag Atomic Member\nconst quuzTag = new Tag(\"boolArray[0]\", null, BIT_STRING); // bool array tag MUST have the data type \"BIT_STRING\" passed in\n```\n\nReading Tags as a `Group`...\n```javascript\nconst { Controller, Tag, TagGroup } = require(\"ethernet-ip\");\n\nconst PLC = new Controller();\nconst group = new TagGroup();\n\n// Add some tags to group\ngroup.add(new Tag(\"contTag\")); // Controller Scope Tag\ngroup.add(new Tag(\"progTag\", \"prog\")); // Program Scope Tag in PLC Program \"prog\"\n\nPLC.connect(\"192.168.1.1\", 0).then(async () =\u003e {\n    await PLC.readTagGroup(group);\n\n    // log the values to the console\n    group.forEach(tag =\u003e {\n        console.log(tag.value);\n    });\n});\n```\n\n#### Writing Tags\n\n**NOTE:** You *MUST* read the tags first or manually provide a valid CIP datatype. The following examples are taking the latter approach.\n\nWriting Tags `Individually`...\n```javascript\nconst { Controller, Tag, EthernetIP } = require(\"ethernet-ip\");\nconst { DINT, BOOL } = EthernetIP.CIP.DataTypes.Types;\n\nconst PLC = new Controller();\n\n// Create Tag Instances\nconst fooTag = new Tag(\"contTag\", null, DINT); // Controller Scope Tag\nconst barTag = new Tag(\"progTag\", \"prog\", BOOL); // Program Scope Tag in PLC Program \"prog\"\n\nPLC.connect(\"192.168.1.1\", 0).then(async () =\u003e {\n\n    // First way to write a new value\n    fooTag.value = 75;\n    await PLC.writeTag(fooTag);\n\n    // Second way to write a new value\n    await PLC.writeTag(barTag, true);\n\n    console.log(fooTag.value);\n    console.log(barTag.value);\n});\n```\n\nWriting Tags as a `Group`...\n```javascript\nconst { Controller, Tag, TagGroup, EthernetIP } = require(\"ethernet-ip\");\nconst { DINT, BOOL } = EthernetIP.CIP.DataTypes.Types;\n\nconst PLC = new Controller();\nconst group = new TagGroup();\n\n// Create Tag Instances\nconst fooTag = new Tag(\"contTag\", null, DINT); // Controller Scope Tag\nconst barTag = new Tag(\"progTag\", \"prog\", BOOL); // Program Scope Tag in PLC Program \"prog\"\n\ngroup.add(fooTag); // Controller Scope Tag\ngroup.add(barTag); // Program Scope Tag in PLC Program \"prog\"\n\nPLC.connect(\"192.168.1.1\", 0).then(async () =\u003e {\n    // Set new values\n    fooTag.value = 75;\n    barTag.value = true;\n\n    // Will only write tags whose Tag.controller_tag !== Tag.value\n    await PLC.writeTagGroup(group);\n\n    group.forEach(tag =\u003e {\n        console.log(tag.value);\n    });\n});\n```\n### Lets Get Fancy\n#### Subscribing to Controller Tags\n\n```javascript\nconst { Controller, Tag } = require(\"ethernet-ip\");\n\nconst PLC = new Controller();\n\n// Add some tags to group\nPLC.subscribe(new Tag(\"contTag\")); // Controller Scope Tag\nPLC.subscribe(new Tag(\"progTag\", \"prog\")); // Program Scope Tag in PLC Program \"prog\"\n\nPLC.connect(\"192.168.1.1\", 0).then(() =\u003e {\n    // Set Scan Rate of Subscription Group to 50 ms (defaults to 200 ms)\n    PLC.scan_rate = 50;\n\n    // Begin Scanning\n    PLC.scan();\n});\n\n// Catch the Tag \"Changed\" and \"Initialized\" Events\nPLC.forEach(tag =\u003e {\n    // Called on the First Successful Read from the Controller\n    tag.on(\"Initialized\", tag =\u003e {\n        console.log(\"Initialized\", tag.value);\n    });\n\n    // Called if Tag.controller_value changes\n    tag.on(\"Changed\", (tag, oldValue) =\u003e {\n        console.log(\"Changed:\", tag.value);\n    });\n});\n```\n\n## Demos\n\n- **Monitor Tags for Changes Demo**\n\n![Simple Demo](http://f.cl.ly/items/3w452r3v3i1s0Z1f2X11/Screen%20recording%202018-03-06%20at%2004.58.30%20PM.gif)\n\n```javascript\nconst { Controller, Tag } = require(\"ethernet-ip\");\n\n// Intantiate Controller\nconst PLC = new Controller();\n\n// Subscribe to Tags\nPLC.subscribe(new Tag(\"TEST_TAG\"););\nPLC.subscribe(new Tag(\"TEST\", \"Prog\"););\nPLC.subscribe(new Tag(\"TEST_REAL\", \"Prog\"););\nPLC.subscribe(new Tag(\"TEST_BOOL\", \"Prog\"););\n\n// Connect to PLC at IP, SLOT\nPLC.connect(\"10.1.60.205\", 5).then(() =\u003e {\n    const { name } = PLC.properties;\n\n    // Log Connected to Console\n    console.log(`\\n\\nConnected to PLC ${name}...\\n`);\n\n    // Begin Scanning Subscription Group\n    PLC.scan();\n});\n\n// Initialize Event Handlers\nPLC.forEach(tag =\u003e {\n    tag.on(\"Changed\", (tag, lastValue) =\u003e {\n        console.log(`${tag.name} changed from ${lastValue} -\u003e ${tag.value}`);\n    });\n})\n```\n\n## Built With\n\n* [NodeJS](https://nodejs.org/en/) - The Engine\n* [javascript - ES2017](https://maven.apache.org/) - The Language\n\n## Contributers\n\n* **Canaan Seaton** - *Owner* - [GitHub Profile](https://github.com/cmseaton42) - [Personal Website](http://www.canaanseaton.com/)\n* **Patrick McDonagh** - *Collaborator* - [GitHub Profile](https://github.com/patrickjmcd)\n* **Jeremy Henson** - *Collaborator* - [Github Profile](https://github.com/jhenson29)\n  \n## Related Projects\n\n* [Node Red](https://github.com/netsmarttech/node-red-contrib-cip-ethernet-ip#readme)\n\nWanna *become* a contributor? [Here's](https://github.com/cmseaton42/node-ethernet-ip/blob/master/CONTRIBUTING.md) how!\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENCE](https://github.com/cmseaton42/node-ethernet-ip/blob/master/LICENSE) file for details\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmseaton42%2Fnode-ethernet-ip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcmseaton42%2Fnode-ethernet-ip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmseaton42%2Fnode-ethernet-ip/lists"}