aes70 2.0.18 → 2.0.19

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/Changelog CHANGED
@@ -2,6 +2,104 @@
2
2
 
3
3
  All notable changes and version updates will be documented in this file.
4
4
 
5
+ ## [2.0.19] - 2026-03-13
6
+
7
+ - Remove ws dependency. WebSocket connections can use a compatible
8
+ constructor passed to WebSocketConnection.connect() when needed.
9
+
10
+ - ClientConnection: Do not log unsubscribe errors when the connection
11
+ has been closed (CloseError).
12
+
13
+ - TypeScript: Add name property to error class declarations.
14
+
15
+ ## [2.0.18] - 2026-03-11
16
+
17
+ - ClientConnection: Add command duration for UDP. Set expected duration
18
+ on the last command when the device needs time to process.
19
+
20
+ - Connection: Make set_keepalive_interval idempotent when called
21
+ multiple times with the same interval.
22
+
23
+ - printDevice: Add --progress.
24
+
25
+ - fetchDeviceContent: Handle BigInt and OcaStatus.BadMethod.
26
+
27
+ - AbstractUdpConnection: Fix retry logic.
28
+
29
+ ## [2.0.17] - 2025-12-02
30
+
31
+ - Connection: Do not send keepalive after close.
32
+
33
+ - fetchDeviceContent: Handle BigInt data in JSON output.
34
+
35
+ - Refactor UDP command retry handling; batch commands and avoid spurious
36
+ timeouts with large write buffers.
37
+
38
+ ## [2.0.15] - 2025-11-26
39
+
40
+ - Property: Fix and test alias lookup for renamed properties (e.g. 2023).
41
+
42
+ - Refactor UDP support: connection attempt can be aborted with AbortSignal;
43
+ DNS lookup configurable for IPv4 or IPv6.
44
+
45
+ - Events: Do not throw from removeEventHandler (fixes cleanup with
46
+ removeAllEventHandlers).
47
+
48
+ - OCP1/OcaInterval: Fix template class decoder.
49
+
50
+ ## [2.0.9] - 2025-11-25
51
+
52
+ - AbstractUdpConnection: Close socket on failure when device does not
53
+ respond with keepalive in time.
54
+
55
+ ## [2.0.8] - 2025-11-24
56
+
57
+ - RemoteDevice: Fix EV2 detection when implementations return status
58
+ codes other than NotImplemented for new EV2 methods.
59
+
60
+ - wait_for_keepalive: Handle error in unsubscribe.
61
+
62
+ ## [2.0.7] - 2025-11-18
63
+
64
+ - OcaInterval: Fix OCP.1 encoder definition.
65
+
66
+ ## [2.0.6] - 2025-11-12
67
+
68
+ - OcaInterval: Fix duplicate import.
69
+
70
+ ## [2.0.5] - 2025-11-12
71
+
72
+ - TypeScript: Use explicit import paths for moduleResolution=nodenext.
73
+
74
+ - Remove deprecated types from AES70-2018.
75
+
76
+ ## [2.0.4] - 2025-10-24
77
+
78
+ - ClientConnection: Add wait_for_keepalive to wait for a single keepalive
79
+ from the device.
80
+
81
+ - Connection: Warn when keepalive interval is large (common ms vs seconds
82
+ mistake).
83
+
84
+ ## [2.0.3] - 2025-10-09
85
+
86
+ - Fix missing inout parameters in generated OCC model.
87
+
88
+ ## [2.0.2] - 2025-10-07
89
+
90
+ - NotificationError: Fix payload parsing.
91
+
92
+ - BaseEvent: Fix error handling.
93
+
94
+ - PropertySync: Implement aliases so properties are available by alias.
95
+
96
+ ## [2.0.1] - 2025-10-07
97
+
98
+ - PropertySync: Use observeProperty.
99
+
100
+ - Introduce CloseError and TimeoutError classes; emit them on close and
101
+ timeout. Suppress unhandled close error warning.
102
+
5
103
  ## [2.0.0] - 2025-10-07
6
104
 
7
105
  - Updates to AES70-2024
@@ -13,7 +111,7 @@ All notable changes and version updates will be documented in this file.
13
111
 
14
112
  ## [1.6.1] - 2025-05-06
15
113
 
16
- - TCPConnection.connect: Add connecSignal to abort
114
+ - TCPConnection.connect: Add connectSignal to abort
17
115
  connection attempts.
18
116
 
19
117
  - Encode arguments earlier. This means that when calling
package/README.md CHANGED
@@ -96,12 +96,23 @@ NodeJS both TCP and UDP are available in addition to that.
96
96
  port: 65000,
97
97
  });
98
98
 
99
- In a web browser using a WebSocket this looks similar.
99
+ In a web browser using a WebSocket this looks similar (the global
100
+ `WebSocket` is used automatically):
100
101
 
101
102
  const connection = await OCA.WebSocketConnection.connect({
102
103
  url: 'ws://example.org',
103
104
  });
104
105
 
106
+ On Node.js, WebSocket support requires passing the WebSocket constructor
107
+ as the second argument to `connect()`, since there is no built-in
108
+ WebSocket. For example, install the `ws` package and use:
109
+
110
+ import { WebSocket } from 'ws';
111
+ const connection = await WebSocketConnection.connect(
112
+ { url: 'ws://example.org' },
113
+ WebSocket
114
+ );
115
+
105
116
  The next step is to discover what kind of objects the device has. This can be
106
117
  done using the method `RemoteDevice.get_device_tree()` method.
107
118
 
@@ -178,7 +189,7 @@ connection.on('receive', (pdu) => {
178
189
  pendingCommand.name,
179
190
  pendingCommand.get_arguments(),
180
191
  '->',
181
- Types.OcaStatus.getName(pdu.status_code)
192
+ Types.OcaStatus.getName(pdu.status_code),
182
193
  );
183
194
  }
184
195
  } else {
package/dist/AES70.es5.js CHANGED
@@ -1949,7 +1949,7 @@
1949
1949
 
1950
1950
  const e = new CloseError(error);
1951
1951
  pendingCommands.forEach((pendingCommand, id) => {
1952
- pendingCommand.handleError(structuredClone(e));
1952
+ pendingCommand.handleError(e);
1953
1953
  });
1954
1954
 
1955
1955
  subscribers.forEach((cb) => {
@@ -28729,7 +28729,8 @@
28729
28729
  } else if (S.version > 0 && !S.has_subscribers()) {
28730
28730
  dropSubscribers();
28731
28731
  this._doUnsubscribe(S, event).catch((error) => {
28732
- console.error('Unsubscribe failed: ', error);
28732
+ if (error.name === 'aes70.CloseError') return;
28733
+ console.error('Unsubscribe failed: %o', error);
28733
28734
  });
28734
28735
  }
28735
28736
  };
@@ -30703,21 +30704,32 @@
30703
30704
  }
30704
30705
  }
30705
30706
 
30707
+ const globalWebSocket =
30708
+ typeof globalThis !== 'undefined' ? globalThis.WebSocket : undefined;
30709
+
30706
30710
  /**
30707
30711
  * Connection which implements OCP.1 with WebSocket transport.
30712
+ * Works in both browser and Node.js. In the browser the global WebSocket
30713
+ * is used when not passed; on Node.js the WebSocket constructor must be
30714
+ * passed as the second argument (e.g. from the 'ws' package).
30708
30715
  */
30709
30716
  class WebSocketConnection extends WebSocketConnectionBase {
30710
30717
  /**
30711
30718
  * Connect to the given endpoint.
30712
30719
  *
30713
30720
  * @param {object} options
30714
- * @param {String} options.url
30715
- * Endpoint WebSocket url.
30716
- * @returns {Promise<WebSocketConnection>}
30717
- * The connection.
30721
+ * @param {String} options.url - Endpoint WebSocket url.
30722
+ * @param {Function} [WebSocket] - WebSocket constructor. Optional in browser (global WebSocket is used). Required on Node.js (e.g. import WebSocket from 'ws').
30723
+ * @returns {Promise<WebSocketConnection>} - The connection.
30718
30724
  */
30719
- static connect(options) {
30720
- return super.connect(WebSocket, options);
30725
+ static connect(options, WebSocket) {
30726
+ const Ctor = WebSocket !== undefined ? WebSocket : globalWebSocket;
30727
+ if (!Ctor) {
30728
+ throw new Error(
30729
+ 'WebSocket constructor is required in this environment. Pass the WebSocket class as the second argument (e.g. from the "ws" package on Node.js).'
30730
+ );
30731
+ }
30732
+ return super.connect(Ctor, options);
30721
30733
  }
30722
30734
 
30723
30735
  _now() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aes70",
3
- "version": "2.0.18",
3
+ "version": "2.0.19",
4
4
  "description": "A controller library for the AES70 protocol.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -41,9 +41,6 @@
41
41
  "url": "https://github.com/DeutscheSoft/AES70.js/issues"
42
42
  },
43
43
  "homepage": "https://github.com/DeutscheSoft/AES70.js#readme",
44
- "optionalDependencies": {
45
- "ws": "^5.2.4"
46
- },
47
44
  "sideEffects": [
48
45
  "src/bundle.browser.js",
49
46
  "dist/AES70.es5.js"
@@ -1,4 +1,5 @@
1
1
  export declare class CloseError extends Error {
2
- error?: Error;
2
+ readonly error?: Error;
3
+ readonly name: 'aes70.CloseError';
3
4
  constructor(error?: Error);
4
5
  }
@@ -158,7 +158,7 @@ export class ClientConnection extends Connection {
158
158
 
159
159
  const e = new CloseError(error);
160
160
  pendingCommands.forEach((pendingCommand, id) => {
161
- pendingCommand.handleError(structuredClone(e));
161
+ pendingCommand.handleError(e);
162
162
  });
163
163
 
164
164
  subscribers.forEach((cb) => {
@@ -1,4 +1,4 @@
1
- import { warn, error } from '../log.js';
1
+ import { warn } from '../log.js';
2
2
 
3
3
  import { Events } from '../events.js';
4
4
 
@@ -17,13 +17,13 @@ import { OcaCodingManager } from './ControlClasses/OcaCodingManager.js';
17
17
  import { OcaDiagnosticManager } from './ControlClasses/OcaDiagnosticManager.js';
18
18
  import { OcaBlock } from './ControlClasses/OcaBlock.js';
19
19
  import { RemoteError } from './remote_error.js';
20
- import { OcaStatus } from '../types/OcaStatus.js';
21
20
  import tree_to_rolemap from './tree_to_rolemap.js';
22
21
 
23
22
  import * as RemoteControlClasses from './ControlClasses.js';
24
23
 
25
24
  import { OcaManagerDefaultObjectNumbers } from '../types/OcaManagerDefaultObjectNumbers.js';
26
25
  import { OcaNotificationDeliveryMode } from '../types/OcaNotificationDeliveryMode.js';
26
+ import { CloseError } from '../close_error.js';
27
27
 
28
28
  const emptyUint8Array = new Uint8Array(0);
29
29
 
@@ -314,7 +314,8 @@ export class RemoteDevice extends Events {
314
314
  } else if (S.version > 0 && !S.has_subscribers()) {
315
315
  dropSubscribers();
316
316
  this._doUnsubscribe(S, event).catch((error) => {
317
- console.error('Unsubscribe failed: ', error);
317
+ if (error.name === 'aes70.CloseError') return;
318
+ console.error('Unsubscribe failed: %o', error);
318
319
  });
319
320
  }
320
321
  };
@@ -1,17 +1,20 @@
1
1
  import {
2
2
  WebSocketConnectionBase,
3
3
  IWebSocketConnectionBaseOptions,
4
+ IWebSocketLike,
5
+ WebSocketConstructor,
4
6
  } from './websocket_connection_base.js';
5
7
 
6
8
  export type IWebSocketConnectionOptions = IWebSocketConnectionBaseOptions;
9
+ export type { IWebSocketLike, WebSocketConstructor };
7
10
 
8
11
  export class WebSocketConnection extends WebSocketConnectionBase {
9
- constructor(ws: WebSocket, options: WebSocketConnectionOptions);
10
- static connectWebSocket(
11
- WebSocket: typeof WebSocket,
12
- options: WebSocketConnectionOptions
13
- ): Promise<WebSocket>;
12
+ constructor(ws: IWebSocketLike, options: IWebSocketConnectionOptions);
14
13
  static connect(
15
- options: WebSocketConnectionOptions
14
+ options: IWebSocketConnectionOptions
15
+ ): Promise<WebSocketConnection>;
16
+ static connect(
17
+ options: IWebSocketConnectionOptions,
18
+ WebSocket: WebSocketConstructor
16
19
  ): Promise<WebSocketConnection>;
17
20
  }
@@ -1,20 +1,31 @@
1
1
  import { WebSocketConnectionBase } from './websocket_connection_base.js';
2
2
 
3
+ const globalWebSocket =
4
+ typeof globalThis !== 'undefined' ? globalThis.WebSocket : undefined;
5
+
3
6
  /**
4
7
  * Connection which implements OCP.1 with WebSocket transport.
8
+ * Works in both browser and Node.js. In the browser the global WebSocket
9
+ * is used when not passed; on Node.js the WebSocket constructor must be
10
+ * passed as the second argument (e.g. from the 'ws' package).
5
11
  */
6
12
  export class WebSocketConnection extends WebSocketConnectionBase {
7
13
  /**
8
14
  * Connect to the given endpoint.
9
15
  *
10
16
  * @param {object} options
11
- * @param {String} options.url
12
- * Endpoint WebSocket url.
13
- * @returns {Promise<WebSocketConnection>}
14
- * The connection.
17
+ * @param {String} options.url - Endpoint WebSocket url.
18
+ * @param {Function} [WebSocket] - WebSocket constructor. Optional in browser (global WebSocket is used). Required on Node.js (e.g. import WebSocket from 'ws').
19
+ * @returns {Promise<WebSocketConnection>} - The connection.
15
20
  */
16
- static connect(options) {
17
- return super.connect(WebSocket, options);
21
+ static connect(options, WebSocket) {
22
+ const Ctor = WebSocket !== undefined ? WebSocket : globalWebSocket;
23
+ if (!Ctor) {
24
+ throw new Error(
25
+ 'WebSocket constructor is required in this environment. Pass the WebSocket class as the second argument (e.g. from the "ws" package on Node.js).'
26
+ );
27
+ }
28
+ return super.connect(Ctor, options);
18
29
  }
19
30
 
20
31
  _now() {
@@ -3,6 +3,27 @@ import {
3
3
  ClientConnection,
4
4
  } from './client_connection.js';
5
5
 
6
+ /**
7
+ * Minimal WebSocket-like interface supported by both browser WebSocket
8
+ * and the Node.js 'ws' library. Used for typing connection options and
9
+ * the optional WebSocket constructor passed to connect().
10
+ */
11
+ export interface IWebSocketLike {
12
+ binaryType: string;
13
+ addEventListener(
14
+ type: string,
15
+ listener: (ev: { data?: ArrayBuffer | Buffer; type?: string }) => void
16
+ ): void;
17
+ removeEventListener(
18
+ type: string,
19
+ listener: (ev: { data?: ArrayBuffer | Buffer; type?: string }) => void
20
+ ): void;
21
+ send(data: ArrayBuffer | Buffer | ArrayBufferView): void;
22
+ close(): void;
23
+ }
24
+
25
+ export type WebSocketConstructor = new (url: string) => IWebSocketLike;
26
+
6
27
  export interface IWebSocketConnectionBaseOptions
7
28
  extends IClientConnectionOptions {
8
29
  url: string;
@@ -14,5 +35,6 @@ export interface IWebSocketConnectionBaseOptions
14
35
  * Browser.
15
36
  */
16
37
  export class WebSocketConnectionBase extends ClientConnection {
38
+ constructor(ws: IWebSocketLike, options: IWebSocketConnectionBaseOptions);
17
39
  write(buf: ArrayBuffer): void;
18
40
  }
package/src/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from './index.default.js';
2
- export * from './controller/websocket_connection_node.js';
2
+ export * from './controller/websocket_connection.js';
3
3
  export * from './controller/tcp_connection.js';
4
4
  export * from './controller/udp_connection.js';
package/src/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from './index.default.js';
2
- export * from './controller/websocket_connection_node.js';
2
+ export * from './controller/websocket_connection.js';
3
3
  export * from './controller/tcp_connection.js';
4
4
  export * from './controller/udp_connection.js';
@@ -1,3 +1,4 @@
1
1
  export declare class TimeoutError extends Error {
2
+ readonly name: 'aes70.TimeoutError';
2
3
  constructor();
3
4
  }
@@ -1,18 +0,0 @@
1
- import {
2
- WebSocketConnectionBase,
3
- IWebSocketConnectionBaseOptions,
4
- } from './websocket_connection_base.js';
5
- import WebSocket from 'ws';
6
-
7
- export type IWebSocketConnectionOptions = IWebSocketConnectionBaseOptions;
8
-
9
- export class WebSocketConnection extends WebSocketConnectionBase {
10
- constructor(ws: WebSocket, options: WebSocketConnectionOptions);
11
- static connectWebSocket(
12
- WebSocket: typeof WebSocket,
13
- options: WebSocketConnectionOptions
14
- ): Promise<WebSocket>;
15
- static connect(
16
- options: WebSocketConnectionOptions
17
- ): Promise<WebSocketConnection>;
18
- }
@@ -1,24 +0,0 @@
1
- /* eslint-env node */
2
-
3
- import WebSocket from 'ws';
4
- import { performance } from 'perf_hooks';
5
- import { WebSocketConnectionBase } from './websocket_connection_base.js';
6
-
7
- /**
8
- * Connection which implements OCP.1 with WebSocket transport.
9
- */
10
- export class WebSocketConnection extends WebSocketConnectionBase {
11
- /**
12
- * Connect to the given endpoint.
13
- *
14
- * @param {String} options.url - Endpoint WebSocket url.
15
- * @returns {Promise<WebSocketConnection>} - The connection.
16
- */
17
- static async connect(options) {
18
- return super.connect(WebSocket, options);
19
- }
20
-
21
- _now() {
22
- return performance.now();
23
- }
24
- }