node-red-contrib-uos-nats 0.2.100 → 0.2.101

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.
@@ -8,18 +8,14 @@ const providerCache = new Map();
8
8
  const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
9
9
 
10
10
  module.exports = function (RED) {
11
- async function resolveVariableKey(nc, providerId, key, node, payloads) {
11
+ // Helper to get or fetch provider definition
12
+ async function getProviderDefinition(nc, providerId, node, payloads) {
12
13
  const cacheKey = `${providerId}`;
13
14
  const cached = providerCache.get(cacheKey);
14
15
 
15
16
  // Check cache
16
17
  if (cached && (Date.now() - cached.timestamp < CACHE_TTL)) {
17
- const variable = cached.definition.variables.find(v => v.key === key);
18
- if (variable) {
19
- node.debug && node.debug(`Key '${key}' resolved to ID ${variable.id} (cached)`);
20
- // Return full object including type
21
- return { id: variable.id, dataType: variable.dataType, fingerprint: cached.definition.fingerprint };
22
- }
18
+ return cached.definition;
23
19
  }
24
20
 
25
21
  // Query provider definition
@@ -28,7 +24,6 @@ module.exports = function (RED) {
28
24
  const query = payloads.buildReadProviderDefinitionQuery();
29
25
 
30
26
  // Strategy 1: Direct Query (v1.loc.<provider>.def.qry.read)
31
- // This is required for providers like Node-RED itself or simple Python scripts
32
27
  const directSubject = `v1.loc.${providerId}.def.qry.read`;
33
28
  try {
34
29
  const response = await nc.request(directSubject, query, { timeout: 1000 });
@@ -38,7 +33,6 @@ module.exports = function (RED) {
38
33
  }
39
34
 
40
35
  // Strategy 2: Registry Query (v1.loc.registry.providers.<provider>.def.qry.read)
41
- // Fallback for managed providers
42
36
  if (!definition) {
43
37
  const registrySubject = `v1.loc.registry.providers.${providerId}.def.qry.read`;
44
38
  const response = await nc.request(registrySubject, query, { timeout: 2000 });
@@ -55,6 +49,17 @@ module.exports = function (RED) {
55
49
  timestamp: Date.now()
56
50
  });
57
51
 
52
+ return definition;
53
+
54
+ } catch (err) {
55
+ throw new Error(`Failed to fetch definition for '${providerId}': ${err.message}`);
56
+ }
57
+ }
58
+
59
+ async function resolveVariableKey(nc, providerId, key, node, payloads) {
60
+ try {
61
+ const definition = await getProviderDefinition(nc, providerId, node, payloads);
62
+
58
63
  // Find variable by key
59
64
  const variable = definition.variables.find(v => v.key === key);
60
65
  if (!variable) {
@@ -69,6 +74,7 @@ module.exports = function (RED) {
69
74
  }
70
75
  }
71
76
 
77
+
72
78
  function DataHubWriteNode(config) {
73
79
  RED.nodes.createNode(this, config);
74
80
  const node = this;
@@ -218,6 +224,38 @@ module.exports = function (RED) {
218
224
  let varId = node.resolvedId;
219
225
  let varType = node.resolvedDataType;
220
226
 
227
+ // Logic to ensure we have a fingerprint (critical for strict providers)
228
+ // If we have an ID but no fingerprint, we must fetch the definition.
229
+ if (varId && (node.resolvedFingerprint === BigInt(0) || !node.resolvedFingerprint)) {
230
+ try {
231
+ node.status({ fill: 'yellow', shape: 'dot', text: 'fetching definition...' });
232
+ // Reuse resolveVariableKey logic but just to get definition?
233
+ // We can't use resolveVariableKey easily if we don't have a key.
234
+ // But we can peek into the cache directly or force a lookup.
235
+ // Let's call a simplified lookup.
236
+
237
+ // We don't have a dedicated function for "getDefinition", so we construct it or assume key is available?
238
+ // If user selected from list, we might NOT have the key in config (if legacy)?
239
+ // But usually we do.
240
+ // If we don't have key, we can matches by ID.
241
+
242
+ const definitions = await getProviderDefinition(nc, node.providerId, node, node.payloads);
243
+ node.resolvedFingerprint = definitions.fingerprint;
244
+ currentFingerprint = definitions.fingerprint;
245
+
246
+ // Optional: Verify ID matches and get Type
247
+ const foundVar = definitions.variables.find(v => v.id === varId);
248
+ if (foundVar) {
249
+ varType = foundVar.dataType;
250
+ node.resolvedDataType = varType; // update cache
251
+ }
252
+
253
+ } catch (e) {
254
+ node.warn(`Could not fetch fingerprint for provider ${node.providerId}: ${e.message}`);
255
+ // Non-fatal? If strict, write will fail. If not, 0 might work.
256
+ }
257
+ }
258
+
221
259
  if (!varId && node.variableKey) {
222
260
  node.status({ fill: 'yellow', shape: 'dot', text: 'resolving key...' });
223
261
  const resolved = await resolveVariableKey(nc, node.providerId, node.variableKey, node, node.payloads);
@@ -230,14 +268,6 @@ module.exports = function (RED) {
230
268
  currentFingerprint = resolved.fingerprint;
231
269
 
232
270
  node.status({ fill: 'green', shape: 'ring', text: 'ready' });
233
- } else if (varId) {
234
- // If we are using a manual ID, we might have resolved fingerprint earlier?
235
- // If not, we try to resolve if cache exists? To get logic for Fingerprint.
236
- // But if user provided ID manually, we don't have a lookup trigger.
237
- // We might default to 0.
238
- // OR we could lazily fetch definition just for Fingerprint?
239
- // For now, let's leave it as 0 if manual ID is used without key.
240
- // But if we resolved earlier, we have it.
241
271
  }
242
272
 
243
273
  varsToWrite.push({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-uos-nats",
3
- "version": "0.2.100",
3
+ "version": "0.2.101",
4
4
  "description": "Node-RED nodes for Weidmüller u-OS Data Hub. Read, write, and provide variables via NATS protocol with OAuth2 authentication. Features: Variable Key resolution, custom icons, example flows, and provider definition caching.",
5
5
  "author": {
6
6
  "name": "IoTUeli",