@syncbridge/serialport 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Copyright (c) 2025 Panates (Panates Teknoloji Yatirim A.S.). All rights reserved.
2
+
3
+ This software and associated documentation files (the "Software") are
4
+ the proprietary property of Panates and are protected by copyright laws
5
+ and international copyright treaties.
6
+
7
+ Unauthorized copying, distribution, modification, reverse engineering,
8
+ or use of this software, in whole or in part, is strictly prohibited
9
+ without the express written permission of Panates.
10
+
11
+ This Software is provided solely for use in accordance with the terms
12
+ of a valid license agreement. Any unauthorized use may result in
13
+ civil and/or criminal penalties.
14
+
15
+ For licensing inquiries, please contact: info@panates.com
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # SyncBridge Ngrok Connectors
@@ -0,0 +1,37 @@
1
+ import { Buffer } from 'node:buffer';
2
+ import type { PortInfo } from '@serialport/bindings-interface';
3
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
4
+ import reconnectCore from 'reconnect-core';
5
+ import { SerialPort } from 'serialport';
6
+ import { SerialClientReconnectVariables, SerialClientVariables } from './serial-client.variables.js';
7
+ export declare class SerialClientComponent<TEvents extends SerialClientComponent.Events = SerialClientComponent.Events> extends IoClientBaseComponent<TEvents> {
8
+ readonly protocol: string;
9
+ protected _connectionManager?: ReturnType<typeof socketReconnect>;
10
+ protected _serialPort?: SerialPort;
11
+ protected _stopping?: boolean;
12
+ values: SerialClientVariables;
13
+ get connected(): boolean;
14
+ protected _start(abortSignal: AbortSignal): Promise<void>;
15
+ protected _stop(): Promise<void>;
16
+ write(data: string | Buffer): void;
17
+ list(): Promise<PortInfo[]>;
18
+ }
19
+ declare const socketReconnect: reconnectCore.CustomModule<any, any>;
20
+ /**
21
+ * @namespace
22
+ */
23
+ export declare namespace SerialClientComponent {
24
+ interface Events extends IoClientBaseComponent.Events {
25
+ connect: [];
26
+ disconnect: [error: Error | undefined];
27
+ data: [data: Buffer];
28
+ reconnecting: [n: number, delay: number];
29
+ reconnect: [];
30
+ write: [data: Buffer | string];
31
+ }
32
+ const Variables: typeof SerialClientVariables;
33
+ type Variables = SerialClientVariables;
34
+ const ReconnectVariables: typeof SerialClientReconnectVariables;
35
+ type ReconnectVariables = SerialClientReconnectVariables;
36
+ }
37
+ export {};
@@ -0,0 +1,146 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import EventEmitter from 'node:events';
3
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
4
+ import { Component, ServiceStatus } from '@syncbridge/common';
5
+ import colors from 'ansi-colors';
6
+ import { toIntDef } from 'putil-varhelpers';
7
+ import reconnectCore from 'reconnect-core';
8
+ import { SerialPort } from 'serialport';
9
+ import { noOp } from '../constants.js';
10
+ import { SerialClientReconnectVariables, SerialClientVariables, } from './serial-client.variables.js';
11
+ let SerialClientComponent = class SerialClientComponent extends IoClientBaseComponent {
12
+ protocol = 'serial';
13
+ _connectionManager;
14
+ _serialPort;
15
+ _stopping;
16
+ get connected() {
17
+ return this._connectionManager?.connected ?? false;
18
+ }
19
+ async _start(abortSignal) {
20
+ await super._start(abortSignal);
21
+ this._stopping = false;
22
+ let reconnecting = false;
23
+ this._connectionManager = socketReconnect({
24
+ ...this.values.reconnect,
25
+ })
26
+ .on('error', err => {
27
+ this.emit('error', err);
28
+ })
29
+ .on('connect', (emitter) => {
30
+ const serialPort = emitter.port;
31
+ if (this._serialPort !== serialPort) {
32
+ this._serialPort = serialPort;
33
+ serialPort.on('data', (chunk) => this.emit('data', chunk));
34
+ }
35
+ if (reconnecting)
36
+ this.emit('reconnect');
37
+ reconnecting = false;
38
+ this.emit('connect');
39
+ this.logger?.info(`Connected to "${colors.cyan(this.values.port)}" serial port`);
40
+ this.setStatus(ServiceStatus.started);
41
+ })
42
+ .on('reconnect', (n, delay) => {
43
+ if (n === 0 && delay === 0)
44
+ return;
45
+ this.logger?.warn(`Connection failed (${colors.cyan(String(n + 1))}). Will be retried after ${colors.cyan(delay + 'ms')}`);
46
+ this.emit('reconnecting', n, delay);
47
+ })
48
+ .on('disconnect', err => {
49
+ this._serialPort = undefined;
50
+ if (this._stopping)
51
+ this.emit('disconnect');
52
+ else {
53
+ this.logger?.info(`Serial port "${colors.cyan(this.values.port)}" disconnected`);
54
+ this.setStatus(ServiceStatus.unhealthy, err.message);
55
+ }
56
+ });
57
+ this.logger?.info(`Connecting to serial port ${colors.cyan(this.values.port)} ...`);
58
+ this._connectionManager.connect({
59
+ path: this.values.port,
60
+ baudRate: this.values.baudRate || 9600,
61
+ dataBits: toIntDef(this.values.dataBits, 8),
62
+ stopBits: toIntDef(this.values.dataBits, 1),
63
+ parity: this.values.parity || 'none',
64
+ rtscts: this.values.rtscts,
65
+ xon: this.values.xon,
66
+ xoff: this.values.xoff,
67
+ xany: this.values.xany,
68
+ hupcl: this.values.hupcl,
69
+ });
70
+ }
71
+ async _stop() {
72
+ if (!this._connectionManager)
73
+ return;
74
+ this._stopping = true;
75
+ const connectionManager = this._connectionManager;
76
+ this._connectionManager = undefined;
77
+ /** istanbul ignore else */
78
+ if (connectionManager.connected) {
79
+ return new Promise(resolve => {
80
+ connectionManager.once('disconnect', async () => {
81
+ await this.emitAsync('stop').catch(noOp);
82
+ resolve();
83
+ });
84
+ connectionManager.disconnect();
85
+ connectionManager.reset();
86
+ });
87
+ }
88
+ else {
89
+ connectionManager.disconnect();
90
+ connectionManager.reset();
91
+ }
92
+ }
93
+ write(data) {
94
+ if (!(this._serialPort && this._connectionManager?.connected)) {
95
+ throw new Error(`Can't write while serial port is not connected`);
96
+ }
97
+ this.emit('transmit', data);
98
+ this._serialPort.write(data);
99
+ }
100
+ async list() {
101
+ return await SerialPort.list();
102
+ }
103
+ };
104
+ __decorate([
105
+ Component.UseVariables(),
106
+ __metadata("design:type", SerialClientVariables)
107
+ ], SerialClientComponent.prototype, "values", void 0);
108
+ SerialClientComponent = __decorate([
109
+ Component({
110
+ className: 'SerialPort',
111
+ displayName: 'Serial Port',
112
+ description: 'Serial port connection component',
113
+ tags: ['serial', 'rs232', 'client', 'connection'],
114
+ })
115
+ ], SerialClientComponent);
116
+ export { SerialClientComponent };
117
+ const socketReconnect = reconnectCore(args => {
118
+ const port = new SerialPort({
119
+ ...args,
120
+ autoOpen: false,
121
+ });
122
+ const emitter = new EventEmitter();
123
+ port.on('open', () => {
124
+ emitter.port = port;
125
+ emitter.emit('connect', port);
126
+ });
127
+ port.on('error', err => {
128
+ emitter.emit('error', err);
129
+ });
130
+ port.on('close', () => {
131
+ emitter.emit('disconnect');
132
+ });
133
+ port.open(err => {
134
+ if (err) {
135
+ emitter.emit('error', err);
136
+ }
137
+ });
138
+ return emitter;
139
+ });
140
+ /**
141
+ * @namespace
142
+ */
143
+ (function (SerialClientComponent) {
144
+ SerialClientComponent.Variables = SerialClientVariables;
145
+ SerialClientComponent.ReconnectVariables = SerialClientReconnectVariables;
146
+ })(SerialClientComponent || (SerialClientComponent = {}));
@@ -0,0 +1,25 @@
1
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
2
+ /**
3
+ * Reconnect variables
4
+ */
5
+ export declare class SerialClientReconnectVariables {
6
+ strategy: 'fibonacci' | 'exponential';
7
+ initialDelay: number;
8
+ maxDelay: number;
9
+ }
10
+ /**
11
+ * Variables
12
+ */
13
+ export declare class SerialClientVariables extends IoClientBaseComponent.Variables {
14
+ port: string;
15
+ baudRate: number;
16
+ dataBits: string;
17
+ stopBits: string;
18
+ parity: string;
19
+ rtscts: boolean;
20
+ xon: boolean;
21
+ xoff: boolean;
22
+ xany: boolean;
23
+ hupcl: boolean;
24
+ reconnect: SerialClientReconnectVariables;
25
+ }
@@ -0,0 +1,138 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { IoClientBaseComponent } from '@syncbridge/builtins';
3
+ import { DefineVariable, VariableType } from '@syncbridge/common';
4
+ import { SerialPort } from 'serialport';
5
+ /**
6
+ * Reconnect variables
7
+ */
8
+ export class SerialClientReconnectVariables {
9
+ }
10
+ __decorate([
11
+ DefineVariable({
12
+ type: VariableType.Enum,
13
+ label: 'Reconnection strategy',
14
+ enumValues: ['fibonacci', 'exponential'],
15
+ default: 'fibonacci',
16
+ }),
17
+ __metadata("design:type", String)
18
+ ], SerialClientReconnectVariables.prototype, "strategy", void 0);
19
+ __decorate([
20
+ DefineVariable({
21
+ label: 'Initial delay',
22
+ description: 'Initial delay in milliseconds',
23
+ default: 2000,
24
+ }),
25
+ __metadata("design:type", Number)
26
+ ], SerialClientReconnectVariables.prototype, "initialDelay", void 0);
27
+ __decorate([
28
+ DefineVariable({
29
+ label: 'Maximum delay',
30
+ description: 'Maximum delay in milliseconds',
31
+ default: 10000,
32
+ }),
33
+ __metadata("design:type", Number)
34
+ ], SerialClientReconnectVariables.prototype, "maxDelay", void 0);
35
+ /**
36
+ * Variables
37
+ */
38
+ export class SerialClientVariables extends IoClientBaseComponent.Variables {
39
+ }
40
+ __decorate([
41
+ DefineVariable({
42
+ label: 'Port',
43
+ description: 'The port or the system path of the serial port you want to open. For example, `/dev/tty.XXX` on Mac/Linux, or `COM1` on Windows',
44
+ required: true,
45
+ enumValues: SerialPort.list()
46
+ .then(ports => ports.map(port => port.path))
47
+ .catch(() => []),
48
+ }),
49
+ __metadata("design:type", String)
50
+ ], SerialClientVariables.prototype, "port", void 0);
51
+ __decorate([
52
+ DefineVariable({
53
+ type: VariableType.Number,
54
+ label: 'Baud rate',
55
+ description: 'The baud rate of the port to be opened. This should match one of the commonly available ' +
56
+ 'baud rates, such as 110, 300, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, or 115200. ' +
57
+ 'Custom rates are supported best effort per platform. The device connected to the serial port ' +
58
+ 'is not guaranteed to support the requested baud rate, even if the port itself supports that baud rate.',
59
+ default: 9600,
60
+ required: true,
61
+ }),
62
+ __metadata("design:type", Number)
63
+ ], SerialClientVariables.prototype, "baudRate", void 0);
64
+ __decorate([
65
+ DefineVariable({
66
+ type: VariableType.Enum,
67
+ label: 'Data bits',
68
+ enumValues: ['5', '6', '7', '8', '9'],
69
+ default: '8',
70
+ required: true,
71
+ }),
72
+ __metadata("design:type", String)
73
+ ], SerialClientVariables.prototype, "dataBits", void 0);
74
+ __decorate([
75
+ DefineVariable({
76
+ type: VariableType.Enum,
77
+ label: 'Stop bits',
78
+ enumValues: ['1', '1.5', '2'],
79
+ default: '1',
80
+ }),
81
+ __metadata("design:type", String)
82
+ ], SerialClientVariables.prototype, "stopBits", void 0);
83
+ __decorate([
84
+ DefineVariable({
85
+ type: VariableType.Enum,
86
+ label: 'Parity flow control',
87
+ enumValues: ['none', 'even', 'mark', 'odd', 'space'],
88
+ default: 'none',
89
+ }),
90
+ __metadata("design:type", String)
91
+ ], SerialClientVariables.prototype, "parity", void 0);
92
+ __decorate([
93
+ DefineVariable({
94
+ label: 'RTS/CTS',
95
+ description: 'RTS/CTS flow control',
96
+ default: false,
97
+ }),
98
+ __metadata("design:type", Boolean)
99
+ ], SerialClientVariables.prototype, "rtscts", void 0);
100
+ __decorate([
101
+ DefineVariable({
102
+ label: 'XON',
103
+ description: 'XON flow control',
104
+ default: false,
105
+ }),
106
+ __metadata("design:type", Boolean)
107
+ ], SerialClientVariables.prototype, "xon", void 0);
108
+ __decorate([
109
+ DefineVariable({
110
+ label: 'XOFF',
111
+ description: 'XOFF flow control',
112
+ default: false,
113
+ }),
114
+ __metadata("design:type", Boolean)
115
+ ], SerialClientVariables.prototype, "xoff", void 0);
116
+ __decorate([
117
+ DefineVariable({
118
+ label: 'XANY',
119
+ description: 'XANY flow control',
120
+ default: false,
121
+ }),
122
+ __metadata("design:type", Boolean)
123
+ ], SerialClientVariables.prototype, "xany", void 0);
124
+ __decorate([
125
+ DefineVariable({
126
+ label: 'HUPCL',
127
+ description: 'Drop DTR on close if enabled',
128
+ default: true,
129
+ }),
130
+ __metadata("design:type", Boolean)
131
+ ], SerialClientVariables.prototype, "hupcl", void 0);
132
+ __decorate([
133
+ DefineVariable({
134
+ label: 'Reconnect Options',
135
+ description: 'Connection timeout in milliseconds',
136
+ }),
137
+ __metadata("design:type", SerialClientReconnectVariables)
138
+ ], SerialClientVariables.prototype, "reconnect", void 0);
@@ -0,0 +1 @@
1
+ export * from './components/serial-client.component.js';
package/components.js ADDED
@@ -0,0 +1 @@
1
+ export * from './components/serial-client.component.js';
package/constants.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { AuthorMetadata } from '@syncbridge/common';
2
+ export declare const version = "1";
3
+ export declare const noOp: () => undefined;
4
+ export declare const panatesAuthor: AuthorMetadata;
package/constants.js ADDED
@@ -0,0 +1,7 @@
1
+ export const version = '0.4.1';
2
+ export const noOp = () => undefined;
3
+ export const panatesAuthor = {
4
+ name: 'Panates Technology AS',
5
+ email: 'info@panates.com',
6
+ url: 'https://www.panates.com',
7
+ };
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import * as components from './components.js';
2
+ export { components };
3
+ export * from './components.js';
4
+ declare const cfg: import("@syncbridge/common").IExtensionPackage;
5
+ export default cfg;
package/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { makeExtensionPackage } from '@syncbridge/common';
2
+ import * as components from './components.js';
3
+ export { components };
4
+ export * from './components.js';
5
+ const cfg = makeExtensionPackage({
6
+ processors: [],
7
+ components: Object.values(components),
8
+ });
9
+ export default cfg;
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@syncbridge/serialport",
3
+ "version": "0.4.1",
4
+ "description": "SyncBridge Serial Port connection component",
5
+ "author": "Panates Inc",
6
+ "license": "UNLICENSED",
7
+ "dependencies": {
8
+ "@serialport/bindings-interface": "^1.2.2",
9
+ "ansi-colors": "^4.1.3",
10
+ "fast-tokenizer": "^1.9.0",
11
+ "node-events-async": "^1.5.0",
12
+ "reconnect-core": "^1.3.0",
13
+ "putil-varhelpers": "^1.7.0",
14
+ "serialport": "^13.0.0"
15
+ },
16
+ "peerDependencies": {
17
+ "@syncbridge/common": "^0.4.1",
18
+ "@syncbridge/builtins": "^0.4.1"
19
+ },
20
+ "exports": {
21
+ ".": {
22
+ "types": "./index.d.ts",
23
+ "default": "./index.js"
24
+ },
25
+ "./package.json": "./package.json"
26
+ },
27
+ "type": "module",
28
+ "module": "./index.js",
29
+ "types": "./index.d.ts",
30
+ "engines": {
31
+ "node": ">=20.0"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ }
36
+ }