npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ts-communication

v1.1.0

Published

工业 PLC 通讯库,支持 Siemens S7、Melsec MC、Omron FINS、Inovance、Invt、Delta、GE SRTP、XinJE 和 Modbus。

Downloads

26

Readme

ts-communication

面向 Node.js 和 TypeScript 的工业 PLC 通讯库,提供统一的异步连接、读取、写入和在线监测 API。

所有协议客户端共享同一套方法命名(ConnectServer / ReadInt16 / WriteFloat / ConnectClose)和同一种返回值(OperateResult),切换设备品牌时业务代码基本不用改动,也不需要在业务层处理底层报文。

支持的设备与协议

| 品牌 / 协议 | 客户端类 | 默认端口 | 默认字节序 | | --- | --- | --- | --- | | Siemens S7(S7-200 / 200 Smart / 300 / 400 / 1200 / 1500) | SiemensS7Net | 102 | ABCD | | Melsec MC 二进制 | MelsecMcNetMelsecMcUdp | 6000 | DCBA | | Melsec MC ASCII | MelsecMcAsciiNetMelsecMcAsciiUdp | 6000 | DCBA | | Omron FINS | OmronFinsNetOmronFinsUdp | 9600 | CDAB | | Inovance 汇川(AM / H3U / H5U / Easy / EVO) | InovanceTcpNetInovanceSerialInovanceSerialOverTcp | 502 | CDAB | | Inovance EasyNet | InovanceEasyNet | 8000 | CDAB | | Invt 英威腾 TS600 | InvtModbusTcp | 502 | CDAB | | Delta 台达(DVP / AS300) | DeltaTcpNet | 502 | CDAB | | GE SRTP(PACSystems / 90 系列) | GeSRTPNet | 18245 | DCBA | | XinJE 信捷(XC / XD / XL) | XinJETcpNet | 502 | CDAB | | Modbus | ModbusTcpNetModbusUdpNetModbusRtuModbusRtuOverTcpModbusAsciiModbusAsciiOverTcp | 502 | CDAB | | 调试工具 | PingTestTcpClientTcpServer | — | — |

汇川、英威腾、台达、信捷客户端都继承自 Modbus,地址会按各自的规则自动换算成 Modbus 地址,因此同时具备 Modbus 的全部能力。

安装

npm install ts-communication

使用 ModbusRtuModbusAsciiInovanceSerial 等串口型客户端时,另外安装串口驱动:

npm install serialport

要求 Node.js 18 及以上版本。

快速开始

Siemens S7

import { SiemensPLCS, SiemensS7Net } from 'ts-communication';

const plc = new SiemensS7Net(SiemensPLCS.S1200, '192.168.1.10');
const connected = await plc.ConnectServer();

if (!connected.IsSuccess) {
  throw new Error(connected.Message);
}

const temperature = await plc.ReadFloat('DB1.0');
if (temperature.IsSuccess) {
  console.log(temperature.Content);
}

const written = await plc.WriteFloat('DB1.0', 25.5);
console.log(written.IsSuccess, written.Message);

await plc.ConnectClose();

常用 Siemens 地址:M100M10.2I0.0Q0.0DB1.0DB1.DBD100V100

SiemensPLCS 可选 S1200S1500S300S400S200S200Smart

Melsec MC

import { MelsecMcNet } from 'ts-communication';

const plc = new MelsecMcNet('192.168.1.20', 6000);
const connected = await plc.ConnectServer();
if (!connected.IsSuccess) throw new Error(connected.Message);

const result = await plc.ReadInt16('D100');
if (result.IsSuccess) console.log(result.Content);

await plc.WriteInt16('D100', 1234);
await plc.ConnectClose();

常用三菱地址:M100X10Y10D100W100R100SM100B100ZR100XYBW 等按十六进制解析)。

MC 协议支持随机读取,一次报文读取多个不连续地址:

const random = await plc.ReadRandomInt16(['D100', 'D200', 'W50']);
if (random.IsSuccess) console.log(random.Content); // [v1, v2, v3]

Omron FINS

import { OmronFinsNet } from 'ts-communication';

const plc = new OmronFinsNet('192.168.1.30', 9600);
const connected = await plc.ConnectServer();
if (!connected.IsSuccess) throw new Error(connected.Message);

const result = await plc.ReadUInt16('D100');
if (result.IsSuccess) console.log(result.Content);

await plc.ConnectClose();

常用欧姆龙地址:D100CIO100W100H100A100E100E/EM 区按十六进制解析)、TIM10CNT10,位地址形如 CIO100.05

Inovance 汇川

import { InovanceSeries, InovanceTcpNet } from 'ts-communication';

const plc = new InovanceTcpNet('192.168.1.40', 502, 1);
plc.Series = InovanceSeries.AM;

const connected = await plc.ConnectServer();
if (!connected.IsSuccess) throw new Error(connected.Message);

const result = await plc.ReadInt32('MD0');
if (result.IsSuccess) console.log(result.Content);

await plc.WriteInt32('MD0', 100);
await plc.ConnectClose();

常用汇川地址:M0MX0.0MW0MD0MB0QX0.0IX0.0。地址格式会根据 SeriesAMH3UH5UEasyEVO)自动转换为对应的 Modbus 地址。

Invt 英威腾 TS600

import { InvtModbusTcp } from 'ts-communication';

const plc = new InvtModbusTcp('192.168.1.60', 502, 1);
const connected = await plc.ConnectServer();
if (!connected.IsSuccess) throw new Error(connected.Message);

const result = await plc.ReadInt16('D100');
if (result.IsSuccess) console.log(result.Content);

await plc.WriteInt16('D100', 1234);
await plc.ConnectClose();

常用英威腾地址:M0S0X0(八进制)、Y0(八进制)、D0R0T0C0

Delta 台达

import { DeltaSeries, DeltaTcpNet } from 'ts-communication';

const plc = new DeltaTcpNet('192.168.1.70', 502, 1);
plc.Series = DeltaSeries.Dvp; // 或 DeltaSeries.AS

const connected = await plc.ConnectServer();
if (!connected.IsSuccess) throw new Error(connected.Message);

const result = await plc.ReadInt16('D100');
if (result.IsSuccess) console.log(result.Content);

await plc.WriteInt16('D100', 1234);
await plc.ConnectClose();

常用台达地址:M0S0X0(八进制)、Y0(八进制)、D0T0C0Dvp 适用于 DVP-ES/EX/EC/SS 与 DVP-SA/SC/SX/EH,AS 适用于 AS300。

GE SRTP

import { GeSRTPNet } from 'ts-communication';

const plc = new GeSRTPNet('192.168.1.80', 18245);
const connected = await plc.ConnectServer();
if (!connected.IsSuccess) throw new Error(connected.Message);

const result = await plc.ReadInt16('R100');
if (result.IsSuccess) console.log(result.Content);

const bit = await plc.ReadBool('M100');
if (bit.IsSuccess) console.log(bit.Content);

await plc.WriteInt16('R100', 1234);
await plc.ConnectClose();

常用 GE 地址:R1AI1AQ1(仅字访问)、I1Q1M1T1S1G1SA1SB1SC1。GE 地址从 1 开始计数,有效范围 1–65536。

XinJE 信捷

import { XinJESeries, XinJETcpNet } from 'ts-communication';

const plc = new XinJETcpNet('192.168.1.90', 502, XinJESeries.XD);

const connected = await plc.ConnectServer();
if (!connected.IsSuccess) throw new Error(connected.Message);

const result = await plc.ReadInt16('D100');
if (result.IsSuccess) console.log(result.Content);

await plc.WriteInt16('D100', 1234);
await plc.ConnectClose();

XinJESeries 可选 XCXDXL;位地址(XY)按八进制解析。

Modbus TCP

import { ModbusTcpNet } from 'ts-communication';

const plc = new ModbusTcpNet('192.168.1.50', 502, 1);
const connected = await plc.ConnectServer();
if (!connected.IsSuccess) throw new Error(connected.Message);

const value = await plc.ReadUInt16('100');
if (value.IsSuccess) console.log(value.Content);

await plc.WriteUInt16('100', 88);
await plc.ConnectClose();

Modbus 地址前缀

地址可以携带以下前缀,多个前缀可以组合使用:

| 前缀 | 含义 | 示例 | | --- | --- | --- | | s= | 站号(覆盖客户端的 Station) | s=2;100 | | x= | 读取功能码 | x=4;100(读输入寄存器) | | w= | 写入功能码 | w=6;100 | | format= | 该次访问使用的字节序 | format=ABCD;100 |

支持的功能码:123456151622。位地址可以写成 100.3 的形式(位序号 0–15)。

常用可调选项

plc.Station = 1;                  // 默认站号
plc.AddressStartWithZero = true;  // 地址是否从 0 开始,false 时内部减 1
plc.StationCheckMatch = true;     // 是否校验响应站号
plc.DisableFunctionCode06 = false;// 单字写入是否禁用功能码 06(改用 16)
plc.BroadcastStation = -1;        // 广播站号,命中时不等待响应

ReadCoilReadDiscreteWriteMask 也可直接使用。

Modbus RTU / 串口客户端

串口客户端不使用 ConnectServer,而是配置串口参数后调用 Open() / Close()

import { ModbusRtu } from 'ts-communication';

const plc = new ModbusRtu(1);
plc.PortName = 'COM3';   // Linux 下形如 '/dev/ttyUSB0'
plc.BaudRate = 9600;
plc.DataBits = 8;
plc.StopBits = 1;
plc.Parity = 'none';

const opened = await plc.Open();
if (!opened.IsSuccess) throw new Error(opened.Message);

const result = await plc.ReadInt16('100');
if (result.IsSuccess) console.log(result.Content);

await plc.Close();

汇川串口客户端用法相同,额外设置 Series

import { InovanceSerial, InovanceSeries } from 'ts-communication';

const plc = new InovanceSerial(1);
plc.Series = InovanceSeries.H5U;
plc.PortName = 'COM3';
await plc.Open();

若串口设备通过串口服务器接入网络,改用 ModbusRtuOverTcpInovanceSerialOverTcp,它们走 TCP,使用 ConnectServer() / ConnectClose()

C# 数值类型

JavaScript 的 number 不区分整数宽度。库提供与 PLC 常用类型对应的显式类型类,写入时可以保留 byteshortushortintuintfloatdoublelongulong 的范围与字节宽度。

import { Byte, Float, Int16, UInt16, Int64 } from 'ts-communication';

const byteValue = new Byte(255);
const shortValue = new Int16(-12);
const unsignedValue = new UInt16(60000);
const floatValue = new Float(12.5);
const longValue = new Int64(9007199254740993n);

客户端也提供直接的强类型读写方法:

await plc.ReadInt16('D100');
await plc.ReadUInt32('D102');
await plc.ReadFloat('D104');
await plc.ReadDouble('D106');
await plc.ReadInt64('D110');
await plc.WriteFloat('D104', 12.5);

完整方法集:ReadBoolReadByteReadInt16ReadUInt16ReadInt32ReadUInt32ReadFloatReadDoubleReadInt64ReadUInt64ReadStringRead(原始字节),以及对应的 Write* 方法。ReadInt64 / ReadUInt64 返回 bigint,写入时可传 bigintnumber

当传入 length 时,读取方法返回数组;不传入时返回单个值。

统一结果处理

所有连接、读取和写入操作都返回 OperateResult。访问 Content 前应先检查 IsSuccess

const result = await plc.ReadInt16('D100');
if (result.IsSuccess) {
  console.log(result.Content);
} else {
  console.error(result.Message, result.ErrorCode);
}

OperateResult 字段:IsSuccessContentMessageErrorCode

连接与超时

plc.ConnectTimeOut = 5000;  // 连接超时(毫秒)
plc.ReceiveTimeOut = 5000;  // 接收超时(毫秒)
plc.AutoReConnect = true;   // 请求时若连接已断开,自动重连

读写方法会在需要时自动建立连接,因此 ConnectServer() 主要用于提前确认设备可达。

并发与通信锁

客户端内置通信锁和请求队列,同一个实例上的并发读写会自动串行化,不会互相插入报文:

const [a, b, c] = await Promise.all([
  plc.ReadInt16('D100'),
  plc.ReadInt16('D200'),
  plc.ReadFloat('D300'),
]);

如果外部已经保证了串行访问,可以关闭锁以减少开销:

plc.EnableCommunicationLock = false;

长任务与轮询

库客户端可以在 Node.js Worker、Electron Worker 或其他后台线程中长期复用。建议保持一个客户端实例由一个工作线程独占,并在循环中复用连接:

while (running) {
  const result = await plc.ReadInt16('D100');
  if (result.IsSuccess) {
    console.log(new Date().toISOString(), result.Content);
  }
  await new Promise(resolve => setTimeout(resolve, 1000));
}

字节序

客户端公开 ByteTransformDataFormat,可根据 PLC 配置选择 ABCDBADCCDABDCBA

import { DataFormat } from 'ts-communication';

plc.ByteTransform.DataFormat = DataFormat.ABCD;
plc.ByteTransform.IsStringReverseByteWord = false; // 字符串是否按字内交换字节

各协议的默认字节序见上面的协议表。数值读出来明显不对(例如浮点数变成极大值、32 位整数高低字反了)时,应先确认 PLC 侧的字节排列方式,再调整 DataFormat。Modbus 系客户端还可以只针对单次访问指定:format=DCBA;100

调试工具

import { PingTest, TcpClient, TcpServer } from 'ts-communication';

// 连通性检查
const ping = await PingTest.ping('192.168.1.10');
console.log(ping.success, ping.time, ping.message);
console.log(await PingTest.isHostOnline('192.168.1.10', 2000));

// 手动收发报文
const client = new TcpClient('192.168.1.10', 502);
await client.connect();
const response = await client.sendAndReceive(Buffer.from([0x00, 0x01]), 5000);

// 本地模拟服务端
const server = new TcpServer(5000, '0.0.0.0');
await server.start();
await server.stop();

TypeScript

库内置 TypeScript 类型声明,可直接用于 TypeScript 项目:

import { SiemensS7Net } from 'ts-communication';

从源码构建:

npm run build

注意事项

  • 使用真实设备前,请确认 PLC IP、端口、站号、机架/槽号以及访问权限。
  • Siemens S7-1200/S7-1500 通常使用 TCP 102 端口,并需要在 PLC 组态中允许 PUT/GET 访问。
  • 串口协议需要操作系统具有对应串口权限,并正确配置波特率、数据位、停止位和校验位。
  • 一个客户端实例对应一条物理连接,不要在多个线程/进程之间共享同一个实例。
  • 所有示例都应检查 IsSuccess 后再读取 Content

License

ISC