@effect-opcua/client 0.1.0-alpha.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 +201 -0
- package/README.md +367 -0
- package/dist/Opcua.d.mts +13 -0
- package/dist/Opcua.d.mts.map +1 -0
- package/dist/Opcua.mjs +23 -0
- package/dist/Opcua.mjs.map +1 -0
- package/dist/OpcuaClient.d.mts +27 -0
- package/dist/OpcuaClient.d.mts.map +1 -0
- package/dist/OpcuaClient.mjs +20 -0
- package/dist/OpcuaClient.mjs.map +1 -0
- package/dist/OpcuaError.d.mts +249 -0
- package/dist/OpcuaError.d.mts.map +1 -0
- package/dist/OpcuaError.mjs +97 -0
- package/dist/OpcuaError.mjs.map +1 -0
- package/dist/OpcuaMethod.d.mts +158 -0
- package/dist/OpcuaMethod.d.mts.map +1 -0
- package/dist/OpcuaMethod.mjs +31 -0
- package/dist/OpcuaMethod.mjs.map +1 -0
- package/dist/OpcuaSession.d.mts +247 -0
- package/dist/OpcuaSession.d.mts.map +1 -0
- package/dist/OpcuaSession.mjs +50 -0
- package/dist/OpcuaSession.mjs.map +1 -0
- package/dist/OpcuaSubscription.d.mts +148 -0
- package/dist/OpcuaSubscription.d.mts.map +1 -0
- package/dist/OpcuaSubscription.mjs +45 -0
- package/dist/OpcuaSubscription.mjs.map +1 -0
- package/dist/OpcuaVariable.d.mts +179 -0
- package/dist/OpcuaVariable.d.mts.map +1 -0
- package/dist/OpcuaVariable.mjs +15 -0
- package/dist/OpcuaVariable.mjs.map +1 -0
- package/dist/_virtual/rolldown_runtime.mjs +18 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +7 -0
- package/dist/internal/batch/chunk.d.mts +11 -0
- package/dist/internal/batch/chunk.d.mts.map +1 -0
- package/dist/internal/batch/chunk.mjs +23 -0
- package/dist/internal/batch/chunk.mjs.map +1 -0
- package/dist/internal/batch/keyed.d.mts +50 -0
- package/dist/internal/batch/keyed.d.mts.map +1 -0
- package/dist/internal/batch/keyed.mjs +112 -0
- package/dist/internal/batch/keyed.mjs.map +1 -0
- package/dist/internal/batch/operations.d.mts +25 -0
- package/dist/internal/batch/operations.d.mts.map +1 -0
- package/dist/internal/batch/operations.mjs +213 -0
- package/dist/internal/batch/operations.mjs.map +1 -0
- package/dist/internal/browse/operations.d.mts +15 -0
- package/dist/internal/browse/operations.d.mts.map +1 -0
- package/dist/internal/browse/operations.mjs +72 -0
- package/dist/internal/browse/operations.mjs.map +1 -0
- package/dist/internal/client/make.d.mts +16 -0
- package/dist/internal/client/make.d.mts.map +1 -0
- package/dist/internal/client/make.mjs +76 -0
- package/dist/internal/client/make.mjs.map +1 -0
- package/dist/internal/common/collections.d.mts +5 -0
- package/dist/internal/common/collections.d.mts.map +1 -0
- package/dist/internal/common/collections.mjs +10 -0
- package/dist/internal/common/collections.mjs.map +1 -0
- package/dist/internal/common/constants.d.mts +18 -0
- package/dist/internal/common/constants.d.mts.map +1 -0
- package/dist/internal/common/constants.mjs +19 -0
- package/dist/internal/common/constants.mjs.map +1 -0
- package/dist/internal/common/node-id.d.mts +2 -0
- package/dist/internal/common/node-id.mjs +1 -0
- package/dist/internal/common/options.d.mts +15 -0
- package/dist/internal/common/options.d.mts.map +1 -0
- package/dist/internal/common/options.mjs +22 -0
- package/dist/internal/common/options.mjs.map +1 -0
- package/dist/internal/common/predicates.d.mts +8 -0
- package/dist/internal/common/predicates.d.mts.map +1 -0
- package/dist/internal/common/predicates.mjs +13 -0
- package/dist/internal/common/predicates.mjs.map +1 -0
- package/dist/internal/data-types/enum.d.mts +2 -0
- package/dist/internal/data-types/enum.mjs +3 -0
- package/dist/internal/data-types/manager.d.mts +2 -0
- package/dist/internal/data-types/manager.mjs +3 -0
- package/dist/internal/data-types/model.d.mts +2 -0
- package/dist/internal/data-types/model.mjs +1 -0
- package/dist/internal/data-types/read.d.mts +14 -0
- package/dist/internal/data-types/read.d.mts.map +1 -0
- package/dist/internal/data-types/read.mjs +291 -0
- package/dist/internal/data-types/read.mjs.map +1 -0
- package/dist/internal/data-types/structure.d.mts +2 -0
- package/dist/internal/data-types/structure.mjs +3 -0
- package/dist/internal/events/model.d.mts +72 -0
- package/dist/internal/events/model.d.mts.map +1 -0
- package/dist/internal/events/model.mjs +1 -0
- package/dist/internal/events/wire.d.mts +37 -0
- package/dist/internal/events/wire.d.mts.map +1 -0
- package/dist/internal/events/wire.mjs +127 -0
- package/dist/internal/events/wire.mjs.map +1 -0
- package/dist/internal/metadata/arguments.d.mts +2 -0
- package/dist/internal/metadata/arguments.mjs +3 -0
- package/dist/internal/metadata/methods.d.mts +2 -0
- package/dist/internal/metadata/methods.mjs +3 -0
- package/dist/internal/metadata/service.d.mts +23 -0
- package/dist/internal/metadata/service.d.mts.map +1 -0
- package/dist/internal/metadata/service.mjs +416 -0
- package/dist/internal/metadata/service.mjs.map +1 -0
- package/dist/internal/metadata/variables.d.mts +3 -0
- package/dist/internal/metadata/variables.mjs +3 -0
- package/dist/internal/method/arguments.d.mts +48 -0
- package/dist/internal/method/arguments.d.mts.map +1 -0
- package/dist/internal/method/arguments.mjs +216 -0
- package/dist/internal/method/arguments.mjs.map +1 -0
- package/dist/internal/method/operations.d.mts +19 -0
- package/dist/internal/method/operations.d.mts.map +1 -0
- package/dist/internal/method/operations.mjs +111 -0
- package/dist/internal/method/operations.mjs.map +1 -0
- package/dist/internal/monitoring/options.d.mts +30 -0
- package/dist/internal/monitoring/options.d.mts.map +1 -0
- package/dist/internal/monitoring/options.mjs +260 -0
- package/dist/internal/monitoring/options.mjs.map +1 -0
- package/dist/internal/monitoring/requests.d.mts +16 -0
- package/dist/internal/monitoring/requests.d.mts.map +1 -0
- package/dist/internal/monitoring/requests.mjs +53 -0
- package/dist/internal/monitoring/requests.mjs.map +1 -0
- package/dist/internal/monitoring/runtime.d.mts +14 -0
- package/dist/internal/monitoring/runtime.d.mts.map +1 -0
- package/dist/internal/monitoring/runtime.mjs +321 -0
- package/dist/internal/monitoring/runtime.mjs.map +1 -0
- package/dist/internal/monitoring/samples.d.mts +23 -0
- package/dist/internal/monitoring/samples.d.mts.map +1 -0
- package/dist/internal/monitoring/samples.mjs +45 -0
- package/dist/internal/monitoring/samples.mjs.map +1 -0
- package/dist/internal/session/make.d.mts +11 -0
- package/dist/internal/session/make.d.mts.map +1 -0
- package/dist/internal/session/make.mjs +36 -0
- package/dist/internal/session/make.mjs.map +1 -0
- package/dist/internal/session/service.d.mts +10 -0
- package/dist/internal/session/service.d.mts.map +1 -0
- package/dist/internal/session/service.mjs +232 -0
- package/dist/internal/session/service.mjs.map +1 -0
- package/dist/internal/structures/adapter.d.mts +11 -0
- package/dist/internal/structures/adapter.d.mts.map +1 -0
- package/dist/internal/structures/adapter.mjs +37 -0
- package/dist/internal/structures/adapter.mjs.map +1 -0
- package/dist/internal/structures/model.d.mts +21 -0
- package/dist/internal/structures/model.d.mts.map +1 -0
- package/dist/internal/structures/model.mjs +7 -0
- package/dist/internal/structures/model.mjs.map +1 -0
- package/dist/internal/structures/runtime.d.mts +28 -0
- package/dist/internal/structures/runtime.d.mts.map +1 -0
- package/dist/internal/structures/runtime.mjs +119 -0
- package/dist/internal/structures/runtime.mjs.map +1 -0
- package/dist/internal/subscription/options.d.mts +17 -0
- package/dist/internal/subscription/options.d.mts.map +1 -0
- package/dist/internal/subscription/options.mjs +51 -0
- package/dist/internal/subscription/options.mjs.map +1 -0
- package/dist/internal/subscription/runtime.d.mts +15 -0
- package/dist/internal/subscription/runtime.d.mts.map +1 -0
- package/dist/internal/subscription/runtime.mjs +43 -0
- package/dist/internal/subscription/runtime.mjs.map +1 -0
- package/dist/internal/values/codec.d.mts +53 -0
- package/dist/internal/values/codec.d.mts.map +1 -0
- package/dist/internal/values/codec.mjs +117 -0
- package/dist/internal/values/codec.mjs.map +1 -0
- package/dist/internal/values/normalize.d.mts +33 -0
- package/dist/internal/values/normalize.d.mts.map +1 -0
- package/dist/internal/values/normalize.mjs +177 -0
- package/dist/internal/values/normalize.mjs.map +1 -0
- package/dist/internal/values/result.d.mts +16 -0
- package/dist/internal/values/result.d.mts.map +1 -0
- package/dist/internal/values/result.mjs +15 -0
- package/dist/internal/values/result.mjs.map +1 -0
- package/dist/internal/variable/operations.d.mts +50 -0
- package/dist/internal/variable/operations.d.mts.map +1 -0
- package/dist/internal/variable/operations.mjs +192 -0
- package/dist/internal/variable/operations.mjs.map +1 -0
- package/dist/node-opcua.d.mts +2 -0
- package/dist/node-opcua.mjs +3 -0
- package/package.json +57 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { isPlainRecord } from "../common/predicates.mjs";
|
|
2
|
+
import { monitorConfigurationError } from "../../OpcuaError.mjs";
|
|
3
|
+
import { durationToMillis, positiveIntegerOption, unknownKeys } from "../common/options.mjs";
|
|
4
|
+
import { DataChangeFilter, DataChangeTrigger, DeadbandType, TimestampsToReturn, coerceNodeId } from "node-opcua";
|
|
5
|
+
import { Effect } from "effect";
|
|
6
|
+
|
|
7
|
+
//#region src/internal/monitoring/options.ts
|
|
8
|
+
const defaultCreate = {
|
|
9
|
+
maxItemsPerRequest: 250,
|
|
10
|
+
maxConcurrentRequests: 1
|
|
11
|
+
};
|
|
12
|
+
const allowedOverrideKeys = new Set([
|
|
13
|
+
"samplingInterval",
|
|
14
|
+
"queueSize",
|
|
15
|
+
"discardOldest",
|
|
16
|
+
"filter",
|
|
17
|
+
"timestamps"
|
|
18
|
+
]);
|
|
19
|
+
const allowedCreateKeys = new Set(["maxItemsPerRequest", "maxConcurrentRequests"]);
|
|
20
|
+
const normalizeMonitorItems = (items) => Effect.suspend(() => {
|
|
21
|
+
if (!isPlainRecord(items)) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.items", { cause: "items must be a named item dictionary" }));
|
|
22
|
+
const entries = Object.entries(items);
|
|
23
|
+
if (entries.length === 0) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.items", { cause: "items dictionary must not be empty" }));
|
|
24
|
+
const normalized = [];
|
|
25
|
+
const seenNodeIds = /* @__PURE__ */ new Map();
|
|
26
|
+
for (const [key, value] of entries) {
|
|
27
|
+
if (!isReadableVariableDef(value)) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.items", {
|
|
28
|
+
key,
|
|
29
|
+
cause: "monitor inputs must be readable variable definitions"
|
|
30
|
+
}));
|
|
31
|
+
let rawNodeId;
|
|
32
|
+
try {
|
|
33
|
+
rawNodeId = coerceNodeId(value.nodeId);
|
|
34
|
+
} catch (cause) {
|
|
35
|
+
return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.items", {
|
|
36
|
+
key,
|
|
37
|
+
nodeId: value.nodeId,
|
|
38
|
+
cause
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
const nodeId = rawNodeId.toString();
|
|
42
|
+
const duplicate = seenNodeIds.get(nodeId);
|
|
43
|
+
if (duplicate !== void 0) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.items", {
|
|
44
|
+
key,
|
|
45
|
+
nodeId,
|
|
46
|
+
cause: `duplicate NodeId also used by ${duplicate}`
|
|
47
|
+
}));
|
|
48
|
+
seenNodeIds.set(nodeId, key);
|
|
49
|
+
normalized.push({
|
|
50
|
+
key,
|
|
51
|
+
def: value,
|
|
52
|
+
nodeId,
|
|
53
|
+
rawNodeId
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return Effect.succeed(normalized);
|
|
57
|
+
});
|
|
58
|
+
const validateMonitorOptions = (items, options) => Effect.suspend(() => {
|
|
59
|
+
if (!isPlainRecord(options)) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options", { cause: "options must be an object" }));
|
|
60
|
+
if (options.startup !== "strict" && options.startup !== "bestEffort") return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options.startup", { cause: "startup must be \"strict\" or \"bestEffort\"" }));
|
|
61
|
+
if (options.validation !== "none" && options.validation !== "access" && options.validation !== "strict") return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options.validation", { cause: "validation must be \"none\", \"access\", or \"strict\"" }));
|
|
62
|
+
const bufferError = bufferPolicyError(options.clientBuffer);
|
|
63
|
+
if (bufferError) return Effect.fail(bufferError);
|
|
64
|
+
const globalError = effectiveOptionsError({
|
|
65
|
+
samplingInterval: options.samplingInterval,
|
|
66
|
+
queueSize: options.queueSize,
|
|
67
|
+
discardOldest: options.discardOldest,
|
|
68
|
+
filter: options.filter,
|
|
69
|
+
timestamps: options.timestamps
|
|
70
|
+
});
|
|
71
|
+
if (globalError) return Effect.fail(globalError);
|
|
72
|
+
const itemKeys = new Set(items.map((item) => item.key));
|
|
73
|
+
const overrides = options.overrides;
|
|
74
|
+
if (overrides !== void 0) {
|
|
75
|
+
if (!isPlainRecord(overrides)) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options.overrides", { cause: "overrides must be an object keyed by item name" }));
|
|
76
|
+
for (const [key, override] of Object.entries(overrides)) {
|
|
77
|
+
if (!itemKeys.has(key)) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options.overrides", {
|
|
78
|
+
key,
|
|
79
|
+
cause: "override key does not exist in monitor items"
|
|
80
|
+
}));
|
|
81
|
+
if (!isPlainRecord(override)) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options.overrides", {
|
|
82
|
+
key,
|
|
83
|
+
cause: "override must be an object"
|
|
84
|
+
}));
|
|
85
|
+
const unknown = unknownKeys(override, allowedOverrideKeys);
|
|
86
|
+
if (unknown.length > 0) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options.overrides", {
|
|
87
|
+
key,
|
|
88
|
+
cause: `unsupported override option: ${unknown.join(", ")}`
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const create = options.create;
|
|
93
|
+
if (create !== void 0) {
|
|
94
|
+
if (!isPlainRecord(create)) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options.create", { cause: "create must be an object" }));
|
|
95
|
+
const unknown = unknownKeys(create, allowedCreateKeys);
|
|
96
|
+
if (unknown.length > 0) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options.create", { cause: `unsupported create option: ${unknown.join(", ")}` }));
|
|
97
|
+
}
|
|
98
|
+
const maxItemsPerRequest = create?.maxItemsPerRequest ?? defaultCreate.maxItemsPerRequest;
|
|
99
|
+
const maxConcurrentRequests = create?.maxConcurrentRequests ?? defaultCreate.maxConcurrentRequests;
|
|
100
|
+
if (!positiveIntegerOption(maxItemsPerRequest)) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options.create", { cause: "maxItemsPerRequest must be a positive integer" }));
|
|
101
|
+
if (!positiveIntegerOption(maxConcurrentRequests)) return Effect.fail(makeMonitorConfigurationErrorForOperation("monitor.options.create", { cause: "maxConcurrentRequests must be a positive integer" }));
|
|
102
|
+
return Effect.succeed({
|
|
103
|
+
maxItemsPerRequest,
|
|
104
|
+
maxConcurrentRequests
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
const applyMonitorOptions = (items, options) => Effect.forEach(items, (item) => {
|
|
108
|
+
const override = options.overrides?.[item.key];
|
|
109
|
+
return normalizeEffectiveOptions(item, {
|
|
110
|
+
samplingInterval: override?.samplingInterval ?? options.samplingInterval,
|
|
111
|
+
queueSize: override?.queueSize ?? options.queueSize,
|
|
112
|
+
discardOldest: override?.discardOldest ?? options.discardOldest,
|
|
113
|
+
filter: override?.filter ?? options.filter,
|
|
114
|
+
timestamps: override?.timestamps ?? options.timestamps
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
const normalizeEffectiveOptions = (item, options) => Effect.suspend(() => {
|
|
118
|
+
const error = effectiveOptionsError(options, item.key, item.nodeId);
|
|
119
|
+
if (error) return Effect.fail(error);
|
|
120
|
+
const requested = {
|
|
121
|
+
samplingInterval: durationToMillis(options.samplingInterval, {
|
|
122
|
+
notDuration: "samplingInterval must be a Duration",
|
|
123
|
+
invalidDuration: "samplingInterval must be finite and non-negative"
|
|
124
|
+
}),
|
|
125
|
+
queueSize: options.queueSize,
|
|
126
|
+
discardOldest: options.discardOldest,
|
|
127
|
+
filter: options.filter,
|
|
128
|
+
timestamps: options.timestamps
|
|
129
|
+
};
|
|
130
|
+
const nodeOpcuaFilter = toNodeOpcuaDataChangeFilter(options.filter);
|
|
131
|
+
const timestampsToReturn = toNodeOpcuaTimestamps(options.timestamps);
|
|
132
|
+
return Effect.succeed({
|
|
133
|
+
...item,
|
|
134
|
+
requested,
|
|
135
|
+
nodeOpcuaFilter,
|
|
136
|
+
timestampsToReturn,
|
|
137
|
+
compatibilityKey: compatibilityKey(requested, nodeOpcuaFilter, timestampsToReturn)
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
const effectiveOptionsError = (options, key, nodeId) => {
|
|
141
|
+
const samplingInterval = durationToMillis(options.samplingInterval, {
|
|
142
|
+
notDuration: "samplingInterval must be a Duration",
|
|
143
|
+
invalidDuration: "samplingInterval must be finite and non-negative"
|
|
144
|
+
});
|
|
145
|
+
if (typeof samplingInterval === "string") return makeMonitorConfigurationErrorForOperation("monitor.options.samplingInterval", {
|
|
146
|
+
key,
|
|
147
|
+
nodeId,
|
|
148
|
+
cause: samplingInterval
|
|
149
|
+
});
|
|
150
|
+
if (!positiveIntegerOption(options.queueSize)) return makeMonitorConfigurationErrorForOperation("monitor.options.queueSize", {
|
|
151
|
+
key,
|
|
152
|
+
nodeId,
|
|
153
|
+
cause: "queueSize must be a positive integer"
|
|
154
|
+
});
|
|
155
|
+
if (typeof options.discardOldest !== "boolean") return makeMonitorConfigurationErrorForOperation("monitor.options.discardOldest", {
|
|
156
|
+
key,
|
|
157
|
+
nodeId,
|
|
158
|
+
cause: "discardOldest must be a boolean"
|
|
159
|
+
});
|
|
160
|
+
if (!isMonitorFilter(options.filter)) return makeMonitorConfigurationErrorForOperation("monitor.options.filter", {
|
|
161
|
+
key,
|
|
162
|
+
nodeId,
|
|
163
|
+
cause: "filter must be a MonitorFilter"
|
|
164
|
+
});
|
|
165
|
+
if (!isMonitorTimestamps(options.timestamps)) return makeMonitorConfigurationErrorForOperation("monitor.options.timestamps", {
|
|
166
|
+
key,
|
|
167
|
+
nodeId,
|
|
168
|
+
cause: "timestamps must be \"none\", \"source\", \"server\", or \"both\""
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
const bufferPolicyError = (policy) => {
|
|
172
|
+
if (!policy || policy._tag !== "Sliding" && policy._tag !== "Dropping" || !positiveIntegerOption(policy.capacity)) return makeMonitorConfigurationErrorForOperation("monitor.options.clientBuffer", { cause: "clientBuffer capacity must be a positive integer" });
|
|
173
|
+
};
|
|
174
|
+
const compatibilityKey = (requested, nodeOpcuaFilter, timestampsToReturn) => JSON.stringify({
|
|
175
|
+
samplingInterval: requested.samplingInterval,
|
|
176
|
+
queueSize: requested.queueSize,
|
|
177
|
+
discardOldest: requested.discardOldest,
|
|
178
|
+
filter: nodeOpcuaFilterKey(nodeOpcuaFilter),
|
|
179
|
+
timestamps: timestampsToReturn
|
|
180
|
+
});
|
|
181
|
+
const nodeOpcuaFilterKey = (filter) => {
|
|
182
|
+
if (!filter) return "None";
|
|
183
|
+
const normalized = filter;
|
|
184
|
+
return JSON.stringify({
|
|
185
|
+
trigger: normalized.trigger ?? null,
|
|
186
|
+
deadbandType: normalized.deadbandType ?? null,
|
|
187
|
+
deadbandValue: normalized.deadbandValue ?? null
|
|
188
|
+
});
|
|
189
|
+
};
|
|
190
|
+
const toNodeOpcuaDataChangeFilter = (filter) => filter._tag !== "None" ? new DataChangeFilter({
|
|
191
|
+
trigger: toNodeOpcuaDataChangeTrigger(filter),
|
|
192
|
+
...toNodeOpcuaDeadband(filter)
|
|
193
|
+
}) : void 0;
|
|
194
|
+
const toNodeOpcuaDataChangeTrigger = (filter) => {
|
|
195
|
+
switch (filter._tag) {
|
|
196
|
+
case "None": return DataChangeTrigger.StatusValue;
|
|
197
|
+
case "Status": return DataChangeTrigger.Status;
|
|
198
|
+
case "StatusValue": return DataChangeTrigger.StatusValue;
|
|
199
|
+
case "StatusValueTimestamp": return DataChangeTrigger.StatusValueTimestamp;
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
const toNodeOpcuaDeadband = (filter) => {
|
|
203
|
+
if (filter._tag === "None" || filter._tag === "Status") return {};
|
|
204
|
+
switch (filter.deadband._tag) {
|
|
205
|
+
case "None": return {
|
|
206
|
+
deadbandType: DeadbandType.None,
|
|
207
|
+
deadbandValue: 0
|
|
208
|
+
};
|
|
209
|
+
case "Absolute": return {
|
|
210
|
+
deadbandType: DeadbandType.Absolute,
|
|
211
|
+
deadbandValue: filter.deadband.value
|
|
212
|
+
};
|
|
213
|
+
case "Percent": return {
|
|
214
|
+
deadbandType: DeadbandType.Percent,
|
|
215
|
+
deadbandValue: filter.deadband.value
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
const toNodeOpcuaTimestamps = (timestamps) => {
|
|
220
|
+
switch (timestamps) {
|
|
221
|
+
case "none": return TimestampsToReturn.Neither;
|
|
222
|
+
case "source": return TimestampsToReturn.Source;
|
|
223
|
+
case "server": return TimestampsToReturn.Server;
|
|
224
|
+
case "both": return TimestampsToReturn.Both;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
const isReadableVariableDef = (value) => {
|
|
228
|
+
if (!isPlainRecord(value)) return false;
|
|
229
|
+
return value._tag === "VariableDef" && typeof value.nodeId === "string" && (value.access === "read" || value.access === "readWrite");
|
|
230
|
+
};
|
|
231
|
+
const isMonitorTimestamps = (value) => value === "none" || value === "source" || value === "server" || value === "both";
|
|
232
|
+
const isMonitorFilter = (value) => {
|
|
233
|
+
if (!isPlainRecord(value) || typeof value._tag !== "string") return false;
|
|
234
|
+
switch (value._tag) {
|
|
235
|
+
case "None":
|
|
236
|
+
case "Status": return true;
|
|
237
|
+
case "StatusValue":
|
|
238
|
+
case "StatusValueTimestamp": return isMonitorDeadband(value.deadband);
|
|
239
|
+
default: return false;
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
const isMonitorDeadband = (value) => {
|
|
243
|
+
if (!isPlainRecord(value) || typeof value._tag !== "string") return false;
|
|
244
|
+
switch (value._tag) {
|
|
245
|
+
case "None": return true;
|
|
246
|
+
case "Absolute": return typeof value.value === "number" && Number.isFinite(value.value) && value.value >= 0;
|
|
247
|
+
case "Percent": return typeof value.value === "number" && Number.isFinite(value.value) && value.value >= 0 && value.value <= 100;
|
|
248
|
+
default: return false;
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
const makeMonitorConfigurationErrorForOperation = (operation, options) => monitorConfigurationError({
|
|
252
|
+
operation,
|
|
253
|
+
key: options?.key,
|
|
254
|
+
nodeId: options?.nodeId,
|
|
255
|
+
cause: options?.cause
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
//#endregion
|
|
259
|
+
export { applyMonitorOptions, normalizeMonitorItems, validateMonitorOptions };
|
|
260
|
+
//# sourceMappingURL=options.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.mjs","names":["defaultCreate: NormalizedCreateOptions","normalized: Array<NormalizedMonitorItem<Items>>","rawNodeId: NodeId"],"sources":["../../../src/internal/monitoring/options.ts"],"sourcesContent":["import {\n DataChangeFilter,\n DataChangeTrigger,\n DeadbandType,\n TimestampsToReturn,\n coerceNodeId,\n type NodeId,\n} from \"node-opcua\";\nimport { Effect, type Duration } from \"effect\";\n\nimport type { NodeIdString } from \"../common/node-id.js\";\nimport {\n durationToMillis,\n positiveIntegerOption,\n unknownKeys,\n} from \"../common/options.js\";\nimport { isPlainRecord } from \"../common/predicates.js\";\nimport {\n monitorConfigurationError,\n type OpcuaMonitorConfigurationError,\n} from \"../../OpcuaError.js\";\nimport type { ReadableVariableDef } from \"../../OpcuaVariable.js\";\nimport type {\n BufferPolicy,\n EffectiveMonitorItemOptions,\n MonitorDeadband,\n MonitorFilter,\n MonitorItemDictionary,\n MonitorOptions,\n MonitorTimestamps,\n} from \"../../OpcuaSubscription.js\";\n\nexport type NormalizedCreateOptions = {\n readonly maxItemsPerRequest: number;\n readonly maxConcurrentRequests: number;\n};\n\nexport type NormalizedMonitorItem<Items> = {\n readonly key: keyof Items & string;\n readonly def: ReadableVariableDef;\n readonly nodeId: NodeIdString;\n readonly rawNodeId: NodeId;\n};\n\nexport type EffectiveMonitorItem<Items> = NormalizedMonitorItem<Items> & {\n readonly requested: EffectiveMonitorItemOptions;\n readonly nodeOpcuaFilter?: DataChangeFilter;\n readonly timestampsToReturn: TimestampsToReturn;\n readonly compatibilityKey: string;\n};\n\nconst defaultCreate: NormalizedCreateOptions = {\n maxItemsPerRequest: 250,\n maxConcurrentRequests: 1,\n};\n\nconst allowedOverrideKeys = new Set([\n \"samplingInterval\",\n \"queueSize\",\n \"discardOldest\",\n \"filter\",\n \"timestamps\",\n]);\n\nconst allowedCreateKeys = new Set([\n \"maxItemsPerRequest\",\n \"maxConcurrentRequests\",\n]);\n\nexport const normalizeMonitorItems = <Items extends MonitorItemDictionary>(\n items: Items,\n): Effect.Effect<\n ReadonlyArray<NormalizedMonitorItem<Items>>,\n OpcuaMonitorConfigurationError\n> =>\n Effect.suspend(() => {\n if (!isPlainRecord(items)) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.items\", {\n cause: \"items must be a named item dictionary\",\n }),\n );\n }\n const entries = Object.entries(items);\n if (entries.length === 0) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.items\", {\n cause: \"items dictionary must not be empty\",\n }),\n );\n }\n\n const normalized: Array<NormalizedMonitorItem<Items>> = [];\n const seenNodeIds = new Map<string, string>();\n for (const [key, value] of entries) {\n if (!isReadableVariableDef(value)) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.items\", {\n key,\n cause: \"monitor inputs must be readable variable definitions\",\n }),\n );\n }\n let rawNodeId: NodeId;\n try {\n rawNodeId = coerceNodeId(value.nodeId);\n } catch (cause) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.items\", {\n key,\n nodeId: value.nodeId,\n cause,\n }),\n );\n }\n const nodeId = rawNodeId.toString();\n const duplicate = seenNodeIds.get(nodeId);\n if (duplicate !== undefined) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.items\", {\n key,\n nodeId,\n cause: `duplicate NodeId also used by ${duplicate}`,\n }),\n );\n }\n seenNodeIds.set(nodeId, key);\n normalized.push({\n key: key as keyof Items & string,\n def: value,\n nodeId,\n rawNodeId,\n });\n }\n return Effect.succeed(normalized);\n });\n\nexport const validateMonitorOptions = <Items>(\n items: ReadonlyArray<NormalizedMonitorItem<Items>>,\n options: MonitorOptions<Items>,\n): Effect.Effect<NormalizedCreateOptions, OpcuaMonitorConfigurationError> =>\n Effect.suspend(() => {\n if (!isPlainRecord(options)) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.options\", {\n cause: \"options must be an object\",\n }),\n );\n }\n if (options.startup !== \"strict\" && options.startup !== \"bestEffort\") {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.options.startup\", {\n cause: 'startup must be \"strict\" or \"bestEffort\"',\n }),\n );\n }\n if (\n options.validation !== \"none\" &&\n options.validation !== \"access\" &&\n options.validation !== \"strict\"\n ) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\n \"monitor.options.validation\",\n {\n cause: 'validation must be \"none\", \"access\", or \"strict\"',\n },\n ),\n );\n }\n const bufferError = bufferPolicyError(options.clientBuffer);\n if (bufferError) return Effect.fail(bufferError);\n const globalError = effectiveOptionsError({\n samplingInterval: options.samplingInterval,\n queueSize: options.queueSize,\n discardOldest: options.discardOldest,\n filter: options.filter,\n timestamps: options.timestamps,\n });\n if (globalError) return Effect.fail(globalError);\n\n const itemKeys = new Set(items.map((item) => item.key));\n const overrides = options.overrides;\n if (overrides !== undefined) {\n if (!isPlainRecord(overrides)) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\n \"monitor.options.overrides\",\n {\n cause: \"overrides must be an object keyed by item name\",\n },\n ),\n );\n }\n for (const [key, override] of Object.entries(overrides)) {\n if (!itemKeys.has(key as keyof Items & string)) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\n \"monitor.options.overrides\",\n {\n key,\n cause: \"override key does not exist in monitor items\",\n },\n ),\n );\n }\n if (!isPlainRecord(override)) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\n \"monitor.options.overrides\",\n {\n key,\n cause: \"override must be an object\",\n },\n ),\n );\n }\n const unknown = unknownKeys(override, allowedOverrideKeys);\n if (unknown.length > 0) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\n \"monitor.options.overrides\",\n {\n key,\n cause: `unsupported override option: ${unknown.join(\", \")}`,\n },\n ),\n );\n }\n }\n }\n\n const create = options.create;\n if (create !== undefined) {\n if (!isPlainRecord(create)) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.options.create\", {\n cause: \"create must be an object\",\n }),\n );\n }\n const unknown = unknownKeys(create, allowedCreateKeys);\n if (unknown.length > 0) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.options.create\", {\n cause: `unsupported create option: ${unknown.join(\", \")}`,\n }),\n );\n }\n }\n\n const maxItemsPerRequest =\n create?.maxItemsPerRequest ?? defaultCreate.maxItemsPerRequest;\n const maxConcurrentRequests =\n create?.maxConcurrentRequests ?? defaultCreate.maxConcurrentRequests;\n if (!positiveIntegerOption(maxItemsPerRequest)) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.options.create\", {\n cause: \"maxItemsPerRequest must be a positive integer\",\n }),\n );\n }\n if (!positiveIntegerOption(maxConcurrentRequests)) {\n return Effect.fail(\n makeMonitorConfigurationErrorForOperation(\"monitor.options.create\", {\n cause: \"maxConcurrentRequests must be a positive integer\",\n }),\n );\n }\n return Effect.succeed({\n maxItemsPerRequest,\n maxConcurrentRequests,\n });\n });\n\nexport const applyMonitorOptions = <Items>(\n items: ReadonlyArray<NormalizedMonitorItem<Items>>,\n options: MonitorOptions<Items>,\n): Effect.Effect<\n ReadonlyArray<EffectiveMonitorItem<Items>>,\n OpcuaMonitorConfigurationError\n> =>\n Effect.forEach(items, (item) => {\n const override = options.overrides?.[item.key];\n return normalizeEffectiveOptions(item, {\n samplingInterval: override?.samplingInterval ?? options.samplingInterval,\n queueSize: override?.queueSize ?? options.queueSize,\n discardOldest: override?.discardOldest ?? options.discardOldest,\n filter: override?.filter ?? options.filter,\n timestamps: override?.timestamps ?? options.timestamps,\n });\n });\n\nconst normalizeEffectiveOptions = <Items>(\n item: NormalizedMonitorItem<Items>,\n options: {\n readonly samplingInterval: Duration.Duration;\n readonly queueSize: number;\n readonly discardOldest: boolean;\n readonly filter: MonitorFilter;\n readonly timestamps: MonitorTimestamps;\n },\n): Effect.Effect<EffectiveMonitorItem<Items>, OpcuaMonitorConfigurationError> =>\n Effect.suspend(() => {\n const error = effectiveOptionsError(options, item.key, item.nodeId);\n if (error) return Effect.fail(error);\n const requested = {\n samplingInterval: durationToMillis(options.samplingInterval, {\n notDuration: \"samplingInterval must be a Duration\",\n invalidDuration: \"samplingInterval must be finite and non-negative\",\n }) as number,\n queueSize: options.queueSize,\n discardOldest: options.discardOldest,\n filter: options.filter,\n timestamps: options.timestamps,\n };\n const nodeOpcuaFilter = toNodeOpcuaDataChangeFilter(options.filter);\n const timestampsToReturn = toNodeOpcuaTimestamps(options.timestamps);\n return Effect.succeed({\n ...item,\n requested,\n nodeOpcuaFilter,\n timestampsToReturn,\n compatibilityKey: compatibilityKey(\n requested,\n nodeOpcuaFilter,\n timestampsToReturn,\n ),\n });\n });\n\nconst effectiveOptionsError = (\n options: {\n readonly samplingInterval: Duration.Duration;\n readonly queueSize: number;\n readonly discardOldest: boolean;\n readonly filter: MonitorFilter;\n readonly timestamps: MonitorTimestamps;\n },\n key?: string,\n nodeId?: NodeIdString,\n) => {\n const samplingInterval = durationToMillis(options.samplingInterval, {\n notDuration: \"samplingInterval must be a Duration\",\n invalidDuration: \"samplingInterval must be finite and non-negative\",\n });\n if (typeof samplingInterval === \"string\") {\n return makeMonitorConfigurationErrorForOperation(\n \"monitor.options.samplingInterval\",\n {\n key,\n nodeId,\n cause: samplingInterval,\n },\n );\n }\n if (!positiveIntegerOption(options.queueSize)) {\n return makeMonitorConfigurationErrorForOperation(\n \"monitor.options.queueSize\",\n {\n key,\n nodeId,\n cause: \"queueSize must be a positive integer\",\n },\n );\n }\n if (typeof options.discardOldest !== \"boolean\") {\n return makeMonitorConfigurationErrorForOperation(\n \"monitor.options.discardOldest\",\n {\n key,\n nodeId,\n cause: \"discardOldest must be a boolean\",\n },\n );\n }\n if (!isMonitorFilter(options.filter)) {\n return makeMonitorConfigurationErrorForOperation(\"monitor.options.filter\", {\n key,\n nodeId,\n cause: \"filter must be a MonitorFilter\",\n });\n }\n if (!isMonitorTimestamps(options.timestamps)) {\n return makeMonitorConfigurationErrorForOperation(\n \"monitor.options.timestamps\",\n {\n key,\n nodeId,\n cause: 'timestamps must be \"none\", \"source\", \"server\", or \"both\"',\n },\n );\n }\n return undefined;\n};\n\nconst bufferPolicyError = (policy: BufferPolicy) => {\n if (\n !policy ||\n (policy._tag !== \"Sliding\" && policy._tag !== \"Dropping\") ||\n !positiveIntegerOption(policy.capacity)\n ) {\n return makeMonitorConfigurationErrorForOperation(\n \"monitor.options.clientBuffer\",\n {\n cause: \"clientBuffer capacity must be a positive integer\",\n },\n );\n }\n return undefined;\n};\n\nconst compatibilityKey = (\n requested: EffectiveMonitorItemOptions,\n nodeOpcuaFilter: DataChangeFilter | undefined,\n timestampsToReturn: TimestampsToReturn,\n) =>\n JSON.stringify({\n samplingInterval: requested.samplingInterval,\n queueSize: requested.queueSize,\n discardOldest: requested.discardOldest,\n filter: nodeOpcuaFilterKey(nodeOpcuaFilter),\n timestamps: timestampsToReturn,\n });\n\nconst nodeOpcuaFilterKey = (filter: DataChangeFilter | undefined) => {\n if (!filter) return \"None\";\n const normalized = filter as unknown as {\n readonly trigger?: number;\n readonly deadbandType?: number;\n readonly deadbandValue?: number;\n };\n return JSON.stringify({\n trigger: normalized.trigger ?? null,\n deadbandType: normalized.deadbandType ?? null,\n deadbandValue: normalized.deadbandValue ?? null,\n });\n};\n\nconst toNodeOpcuaDataChangeFilter = (filter: MonitorFilter) =>\n filter._tag !== \"None\"\n ? new DataChangeFilter({\n trigger: toNodeOpcuaDataChangeTrigger(filter),\n ...toNodeOpcuaDeadband(filter),\n })\n : undefined;\n\nconst toNodeOpcuaDataChangeTrigger = (filter: MonitorFilter) => {\n switch (filter._tag) {\n case \"None\":\n return DataChangeTrigger.StatusValue;\n case \"Status\":\n return DataChangeTrigger.Status;\n case \"StatusValue\":\n return DataChangeTrigger.StatusValue;\n case \"StatusValueTimestamp\":\n return DataChangeTrigger.StatusValueTimestamp;\n }\n};\n\nconst toNodeOpcuaDeadband = (\n filter: MonitorFilter,\n): {\n readonly deadbandType?: DeadbandType;\n readonly deadbandValue?: number;\n} => {\n if (filter._tag === \"None\" || filter._tag === \"Status\") return {};\n switch (filter.deadband._tag) {\n case \"None\":\n return {\n deadbandType: DeadbandType.None,\n deadbandValue: 0,\n };\n case \"Absolute\":\n return {\n deadbandType: DeadbandType.Absolute,\n deadbandValue: filter.deadband.value,\n };\n case \"Percent\":\n return {\n deadbandType: DeadbandType.Percent,\n deadbandValue: filter.deadband.value,\n };\n }\n};\n\nconst toNodeOpcuaTimestamps = (timestamps: MonitorTimestamps) => {\n switch (timestamps) {\n case \"none\":\n return TimestampsToReturn.Neither;\n case \"source\":\n return TimestampsToReturn.Source;\n case \"server\":\n return TimestampsToReturn.Server;\n case \"both\":\n return TimestampsToReturn.Both;\n }\n};\n\nconst isReadableVariableDef = (\n value: unknown,\n): value is ReadableVariableDef => {\n if (!isPlainRecord(value)) return false;\n return (\n value._tag === \"VariableDef\" &&\n typeof value.nodeId === \"string\" &&\n (value.access === \"read\" || value.access === \"readWrite\")\n );\n};\n\nconst isMonitorTimestamps = (value: unknown): value is MonitorTimestamps =>\n value === \"none\" ||\n value === \"source\" ||\n value === \"server\" ||\n value === \"both\";\n\nconst isMonitorFilter = (value: unknown): value is MonitorFilter => {\n if (!isPlainRecord(value) || typeof value._tag !== \"string\") return false;\n switch (value._tag) {\n case \"None\":\n case \"Status\":\n return true;\n case \"StatusValue\":\n case \"StatusValueTimestamp\":\n return isMonitorDeadband(value.deadband);\n default:\n return false;\n }\n};\n\nconst isMonitorDeadband = (value: unknown): value is MonitorDeadband => {\n if (!isPlainRecord(value) || typeof value._tag !== \"string\") return false;\n switch (value._tag) {\n case \"None\":\n return true;\n case \"Absolute\":\n return (\n typeof value.value === \"number\" &&\n Number.isFinite(value.value) &&\n value.value >= 0\n );\n case \"Percent\":\n return (\n typeof value.value === \"number\" &&\n Number.isFinite(value.value) &&\n value.value >= 0 &&\n value.value <= 100\n );\n default:\n return false;\n }\n};\n\nconst makeMonitorConfigurationErrorForOperation = (\n operation: string,\n options?: {\n readonly key?: string;\n readonly nodeId?: NodeIdString;\n readonly cause?: unknown;\n },\n) =>\n monitorConfigurationError({\n operation,\n key: options?.key,\n nodeId: options?.nodeId,\n cause: options?.cause,\n });\n"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RevisedMonitorItemOptions } from "../../OpcuaSubscription.mjs";
|
|
2
|
+
import { EffectiveMonitorItem } from "./options.mjs";
|
|
3
|
+
import * as node_opcua2 from "node-opcua";
|
|
4
|
+
import { ClientMonitoredItemBase, ClientMonitoredItemGroup, ClientSubscription } from "node-opcua";
|
|
5
|
+
import { Effect } from "effect";
|
|
6
|
+
|
|
7
|
+
//#region src/internal/monitoring/requests.d.ts
|
|
8
|
+
declare const monitorItems: <Items>(subscription: ClientSubscription, chunk: ReadonlyArray<EffectiveMonitorItem<Items>>) => Effect.Effect<{
|
|
9
|
+
group: ClientMonitoredItemGroup;
|
|
10
|
+
disposeAbort: () => void;
|
|
11
|
+
}, unknown, never>;
|
|
12
|
+
declare const monitoredItemStatusCode: (monitoredItem: ClientMonitoredItemBase | undefined) => node_opcua2.StatusCode;
|
|
13
|
+
declare const revisedMonitorItemOptions: (monitoredItem: ClientMonitoredItemBase | undefined) => RevisedMonitorItemOptions | undefined;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { monitorItems, monitoredItemStatusCode, revisedMonitorItemOptions };
|
|
16
|
+
//# sourceMappingURL=requests.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requests.d.mts","names":[],"sources":["../../../src/internal/monitoring/requests.ts"],"sourcesContent":[],"mappings":";;;;;;;cAYa,oCACG,2BACP,cAAc,qBAAqB,YAAO,MAAA,CAAA;;;AAFnD,CAAA,EAAA,OAAa,EAAA,KAAA,CAAA;AACG,cAyBH,uBAzBG,EAAA,CAAA,aAAA,EA0BC,uBA1BD,GAAA,SAAA,EAAA,GA0BwB,WAAA,CAAY,UA1BpC;AAC4B,cA4B/B,yBA5B+B,EAAA,CAAA,aAAA,EA6B3B,uBA7B2B,GAAA,SAAA,EAAA,GA8BzC,yBA9ByC,GAAA,SAAA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { AttributeIds, StatusCodes } from "node-opcua";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/internal/monitoring/requests.ts
|
|
5
|
+
const monitorItems = (subscription, chunk) => {
|
|
6
|
+
const first = chunk[0];
|
|
7
|
+
return Effect.tryPromise({
|
|
8
|
+
try: (signal) => subscription.monitorItems(chunk.map((item) => ({
|
|
9
|
+
nodeId: item.rawNodeId,
|
|
10
|
+
attributeId: AttributeIds.Value
|
|
11
|
+
})), {
|
|
12
|
+
samplingInterval: first.requested.samplingInterval,
|
|
13
|
+
queueSize: first.requested.queueSize,
|
|
14
|
+
discardOldest: first.requested.discardOldest,
|
|
15
|
+
filter: first.nodeOpcuaFilter
|
|
16
|
+
}, first.timestampsToReturn).then((group) => monitorItemsSuccess(group, signal)),
|
|
17
|
+
catch: (cause) => cause
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const monitoredItemStatusCode = (monitoredItem) => monitoredItem?.statusCode ?? StatusCodes.Bad;
|
|
21
|
+
const revisedMonitorItemOptions = (monitoredItem) => {
|
|
22
|
+
const result = monitoredItem?.result;
|
|
23
|
+
if (!result) return void 0;
|
|
24
|
+
const revised = {
|
|
25
|
+
samplingInterval: typeof result.revisedSamplingInterval === "number" ? result.revisedSamplingInterval : void 0,
|
|
26
|
+
queueSize: typeof result.revisedQueueSize === "number" ? result.revisedQueueSize : void 0
|
|
27
|
+
};
|
|
28
|
+
return revised.samplingInterval === void 0 && revised.queueSize === void 0 ? void 0 : revised;
|
|
29
|
+
};
|
|
30
|
+
const monitorItemsSuccess = (group, signal) => {
|
|
31
|
+
if (signal.aborted) {
|
|
32
|
+
terminateMonitorGroupUnsafe(group);
|
|
33
|
+
return {
|
|
34
|
+
group,
|
|
35
|
+
disposeAbort: () => void 0
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const abort = () => terminateMonitorGroupUnsafe(group);
|
|
39
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
40
|
+
return {
|
|
41
|
+
group,
|
|
42
|
+
disposeAbort: () => {
|
|
43
|
+
signal.removeEventListener("abort", abort);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
const terminateMonitorGroupUnsafe = (group) => {
|
|
48
|
+
group.terminate().catch(() => void 0);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
export { monitorItems, monitoredItemStatusCode, revisedMonitorItemOptions };
|
|
53
|
+
//# sourceMappingURL=requests.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requests.mjs","names":["revised: RevisedMonitorItemOptions"],"sources":["../../../src/internal/monitoring/requests.ts"],"sourcesContent":["import {\n AttributeIds,\n StatusCodes,\n type ClientMonitoredItemBase,\n type ClientMonitoredItemGroup,\n type ClientSubscription,\n} from \"node-opcua\";\nimport { Effect } from \"effect\";\n\nimport type { RevisedMonitorItemOptions } from \"../../OpcuaSubscription.js\";\nimport type { EffectiveMonitorItem } from \"./options.js\";\n\nexport const monitorItems = <Items>(\n subscription: ClientSubscription,\n chunk: ReadonlyArray<EffectiveMonitorItem<Items>>,\n) => {\n const first = chunk[0]!;\n return Effect.tryPromise({\n try: (signal) =>\n subscription\n .monitorItems(\n chunk.map((item) => ({\n nodeId: item.rawNodeId,\n attributeId: AttributeIds.Value,\n })),\n {\n samplingInterval: first.requested.samplingInterval,\n queueSize: first.requested.queueSize,\n discardOldest: first.requested.discardOldest,\n filter: first.nodeOpcuaFilter,\n },\n first.timestampsToReturn,\n )\n .then((group) => monitorItemsSuccess(group, signal)),\n catch: (cause) => cause,\n });\n};\n\nexport const monitoredItemStatusCode = (\n monitoredItem: ClientMonitoredItemBase | undefined,\n) => monitoredItem?.statusCode ?? StatusCodes.Bad;\n\nexport const revisedMonitorItemOptions = (\n monitoredItem: ClientMonitoredItemBase | undefined,\n): RevisedMonitorItemOptions | undefined => {\n const result = monitoredItem?.result as\n | {\n readonly revisedSamplingInterval?: number;\n readonly revisedQueueSize?: number;\n }\n | undefined;\n if (!result) return undefined;\n const revised: RevisedMonitorItemOptions = {\n samplingInterval:\n typeof result.revisedSamplingInterval === \"number\"\n ? result.revisedSamplingInterval\n : undefined,\n queueSize:\n typeof result.revisedQueueSize === \"number\"\n ? result.revisedQueueSize\n : undefined,\n };\n return revised.samplingInterval === undefined &&\n revised.queueSize === undefined\n ? undefined\n : revised;\n};\n\nconst monitorItemsSuccess = (\n group: ClientMonitoredItemGroup,\n signal: AbortSignal,\n) => {\n if (signal.aborted) {\n terminateMonitorGroupUnsafe(group);\n return { group, disposeAbort: () => undefined };\n }\n const abort = () => terminateMonitorGroupUnsafe(group);\n signal.addEventListener(\"abort\", abort, { once: true });\n return {\n group,\n disposeAbort: () => {\n signal.removeEventListener(\"abort\", abort);\n },\n };\n};\n\nconst terminateMonitorGroupUnsafe = (group: ClientMonitoredItemGroup) => {\n void group.terminate().catch(() => undefined);\n};\n"],"mappings":";;;;AAYA,MAAa,gBACX,cACA,UACG;CACH,MAAM,QAAQ,MAAM;AACpB,QAAO,OAAO,WAAW;EACvB,MAAM,WACJ,aACG,aACC,MAAM,KAAK,UAAU;GACnB,QAAQ,KAAK;GACb,aAAa,aAAa;GAC3B,EAAE,EACH;GACE,kBAAkB,MAAM,UAAU;GAClC,WAAW,MAAM,UAAU;GAC3B,eAAe,MAAM,UAAU;GAC/B,QAAQ,MAAM;GACf,EACD,MAAM,mBACP,CACA,MAAM,UAAU,oBAAoB,OAAO,OAAO,CAAC;EACxD,QAAQ,UAAU;EACnB,CAAC;;AAGJ,MAAa,2BACX,kBACG,eAAe,cAAc,YAAY;AAE9C,MAAa,6BACX,kBAC0C;CAC1C,MAAM,SAAS,eAAe;AAM9B,KAAI,CAAC,OAAQ,QAAO;CACpB,MAAMA,UAAqC;EACzC,kBACE,OAAO,OAAO,4BAA4B,WACtC,OAAO,0BACP;EACN,WACE,OAAO,OAAO,qBAAqB,WAC/B,OAAO,mBACP;EACP;AACD,QAAO,QAAQ,qBAAqB,UAClC,QAAQ,cAAc,SACpB,SACA;;AAGN,MAAM,uBACJ,OACA,WACG;AACH,KAAI,OAAO,SAAS;AAClB,8BAA4B,MAAM;AAClC,SAAO;GAAE;GAAO,oBAAoB;GAAW;;CAEjD,MAAM,cAAc,4BAA4B,MAAM;AACtD,QAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,MAAM,CAAC;AACvD,QAAO;EACL;EACA,oBAAoB;AAClB,UAAO,oBAAoB,SAAS,MAAM;;EAE7C;;AAGH,MAAM,+BAA+B,UAAoC;AACvE,CAAK,MAAM,WAAW,CAAC,YAAY,OAAU"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReadableVariableDef } from "../../OpcuaVariable.mjs";
|
|
2
|
+
import { OpcuaSubscriptionEvent } from "../events/model.mjs";
|
|
3
|
+
import { OpcuaStructureRuntime } from "../structures/runtime.mjs";
|
|
4
|
+
import { OpcuaSubscription } from "../../OpcuaSubscription.mjs";
|
|
5
|
+
import { OpcuaAccessDeniedError, OpcuaConfigurationError, OpcuaServiceError } from "../../OpcuaError.mjs";
|
|
6
|
+
import { ClientSubscription } from "node-opcua";
|
|
7
|
+
import { Effect, PubSub } from "effect";
|
|
8
|
+
|
|
9
|
+
//#region src/internal/monitoring/runtime.d.ts
|
|
10
|
+
type ValidateVariable = <const Def extends ReadableVariableDef>(def: Def) => Effect.Effect<unknown, OpcuaAccessDeniedError | OpcuaConfigurationError | OpcuaServiceError>;
|
|
11
|
+
declare const makeSubscriptionService: (unsafeRaw: ClientSubscription, events: PubSub.PubSub<OpcuaSubscriptionEvent>, structureRuntime: OpcuaStructureRuntime, validateVariable: ValidateVariable) => OpcuaSubscription;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { ValidateVariable, makeSubscriptionService };
|
|
14
|
+
//# sourceMappingURL=runtime.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.mts","names":[],"sources":["../../../src/internal/monitoring/runtime.ts"],"sourcesContent":[],"mappings":";;;;;;;;;KAiDY,gBAAA,sBACQ,0BAEb,QACF,MAAA,CAAO,gBAER,yBACA,0BACA;cA2BS,qCACA,4BACH,MAAA,CAAO,OAAO,2CACJ,yCACA,qBACjB"}
|