node-red-contrib-uos-nats 0.1.0

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.
Files changed (51) hide show
  1. package/README.md +92 -0
  2. package/icons/white/datahub-input.svg +4 -0
  3. package/icons/white/datahub-output.svg +4 -0
  4. package/lib/auth.js +27 -0
  5. package/lib/config.js +23 -0
  6. package/lib/consumer.js +41 -0
  7. package/lib/fbs/weidmueller/ucontrol/hub/duration.js +67 -0
  8. package/lib/fbs/weidmueller/ucontrol/hub/provider-definition-changed-event.js +69 -0
  9. package/lib/fbs/weidmueller/ucontrol/hub/provider-definition-state.js +20 -0
  10. package/lib/fbs/weidmueller/ucontrol/hub/provider-definition.js +118 -0
  11. package/lib/fbs/weidmueller/ucontrol/hub/provider-list.js +76 -0
  12. package/lib/fbs/weidmueller/ucontrol/hub/provider.js +59 -0
  13. package/lib/fbs/weidmueller/ucontrol/hub/providers-changed-event.js +69 -0
  14. package/lib/fbs/weidmueller/ucontrol/hub/read-provider-definition-query-request.js +51 -0
  15. package/lib/fbs/weidmueller/ucontrol/hub/read-provider-definition-query-response.js +68 -0
  16. package/lib/fbs/weidmueller/ucontrol/hub/read-providers-query-request.js +51 -0
  17. package/lib/fbs/weidmueller/ucontrol/hub/read-providers-query-response.js +69 -0
  18. package/lib/fbs/weidmueller/ucontrol/hub/read-variables-query-request.js +88 -0
  19. package/lib/fbs/weidmueller/ucontrol/hub/read-variables-query-response.js +69 -0
  20. package/lib/fbs/weidmueller/ucontrol/hub/state-changed-event.js +67 -0
  21. package/lib/fbs/weidmueller/ucontrol/hub/state.js +14 -0
  22. package/lib/fbs/weidmueller/ucontrol/hub/timestamp.js +62 -0
  23. package/lib/fbs/weidmueller/ucontrol/hub/uuid.js +43 -0
  24. package/lib/fbs/weidmueller/ucontrol/hub/variable-access-type.js +17 -0
  25. package/lib/fbs/weidmueller/ucontrol/hub/variable-data-type.js +15 -0
  26. package/lib/fbs/weidmueller/ucontrol/hub/variable-definition.js +115 -0
  27. package/lib/fbs/weidmueller/ucontrol/hub/variable-list.js +106 -0
  28. package/lib/fbs/weidmueller/ucontrol/hub/variable-quality.js +31 -0
  29. package/lib/fbs/weidmueller/ucontrol/hub/variable-value-boolean.js +57 -0
  30. package/lib/fbs/weidmueller/ucontrol/hub/variable-value-duration.js +58 -0
  31. package/lib/fbs/weidmueller/ucontrol/hub/variable-value-float64.js +57 -0
  32. package/lib/fbs/weidmueller/ucontrol/hub/variable-value-int64.js +57 -0
  33. package/lib/fbs/weidmueller/ucontrol/hub/variable-value-string.js +58 -0
  34. package/lib/fbs/weidmueller/ucontrol/hub/variable-value-timestamp.js +58 -0
  35. package/lib/fbs/weidmueller/ucontrol/hub/variable-value.js +45 -0
  36. package/lib/fbs/weidmueller/ucontrol/hub/variable.js +131 -0
  37. package/lib/fbs/weidmueller/ucontrol/hub/variables-changed-event.js +71 -0
  38. package/lib/fbs/weidmueller/ucontrol/hub/write-variables-command.js +69 -0
  39. package/lib/fbs/weidmueller/ucontrol/hub.js +17 -0
  40. package/lib/models.js +1 -0
  41. package/lib/payloads.js +182 -0
  42. package/lib/provider.js +51 -0
  43. package/lib/simulation.js +54 -0
  44. package/lib/subjects.js +11 -0
  45. package/nodes/datahub-input.html +157 -0
  46. package/nodes/datahub-input.js +129 -0
  47. package/nodes/datahub-output.html +36 -0
  48. package/nodes/datahub-output.js +189 -0
  49. package/nodes/uos-config.html +48 -0
  50. package/nodes/uos-config.js +173 -0
  51. package/package.json +25 -0
@@ -0,0 +1,173 @@
1
+ const fetch = require('node-fetch');
2
+ const { connect } = require('nats');
3
+
4
+ if (!process.env.NODE_TLS_REJECT_UNAUTHORIZED) {
5
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
6
+ }
7
+
8
+ let adminRoutesRegistered = false;
9
+
10
+ module.exports = function (RED) {
11
+ function UosConfigNode(config) {
12
+ RED.nodes.createNode(this, config);
13
+ this.host = config.host || '127.0.0.1';
14
+ this.port = Number(config.port) || 49360;
15
+ this.clientName = config.clientName || 'nodered';
16
+ this.scope = config.scope || 'hub.variables.provide hub.variables.readwrite';
17
+ this.tokenEndpoint = config.tokenEndpoint || `https://${this.host}/oauth2/token`;
18
+ this.clientId = this.credentials.clientId;
19
+ this.clientSecret = this.credentials.clientSecret;
20
+ this.tokenInfo = null;
21
+ this.nc = null;
22
+ this.users = 0;
23
+
24
+ if (!this.clientId || !this.clientSecret) {
25
+ this.warn('CLIENT_ID oder CLIENT_SECRET fehlen. Bitte in den Node-RED Einstellungen setzen.');
26
+ }
27
+
28
+ const tokenMarginMs = 60 * 1000;
29
+
30
+ this.getToken = async () => {
31
+ const now = Date.now();
32
+ if (this.tokenInfo && now < this.tokenInfo.expiresAt - tokenMarginMs) {
33
+ return this.tokenInfo.token;
34
+ }
35
+ const params = new URLSearchParams({
36
+ grant_type: 'client_credentials',
37
+ scope: this.scope,
38
+ });
39
+ const basic = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString('base64');
40
+ const res = await fetch(this.tokenEndpoint, {
41
+ method: 'POST',
42
+ headers: {
43
+ Authorization: `Basic ${basic}`,
44
+ 'Content-Type': 'application/x-www-form-urlencoded',
45
+ Accept: 'application/json',
46
+ },
47
+ body: params,
48
+ });
49
+ if (!res.ok) {
50
+ const text = await res.text();
51
+ throw new Error(`Token request failed: ${res.status} ${text}`);
52
+ }
53
+ const json = await res.json();
54
+ if (!json.access_token) {
55
+ throw new Error('Token response missing access_token');
56
+ }
57
+ this.tokenInfo = {
58
+ token: json.access_token,
59
+ expiresAt: now + ((json.expires_in || 3600) * 1000),
60
+ };
61
+ return this.tokenInfo.token;
62
+ };
63
+
64
+ this.ensureConnection = async () => {
65
+ if (this.nc) {
66
+ return this.nc;
67
+ }
68
+ const token = await this.getToken();
69
+ this.nc = await connect({
70
+ servers: `nats://${this.host}:${this.port}`,
71
+ token,
72
+ name: `${this.clientName}-nodered`,
73
+ inboxPrefix: `_INBOX.${this.clientName}`,
74
+ });
75
+ this.nc.closed().then(() => {
76
+ this.nc = null;
77
+ }).catch(() => {
78
+ this.nc = null;
79
+ });
80
+ return this.nc;
81
+ };
82
+
83
+ this.fetchProviders = async () => {
84
+ const token = await this.getToken();
85
+ const res = await fetch(`https://${this.host}/datahub/v1/providers`, {
86
+ headers: {
87
+ Authorization: `Bearer ${token}`,
88
+ Accept: 'application/json',
89
+ },
90
+ });
91
+ if (!res.ok) {
92
+ throw new Error(`Provider list failed: ${res.status}`);
93
+ }
94
+ return res.json();
95
+ };
96
+
97
+ this.fetchProviderVariables = async (providerId) => {
98
+ const token = await this.getToken();
99
+ const res = await fetch(`https://${this.host}/datahub/v1/providers/${providerId}/variables`, {
100
+ headers: {
101
+ Authorization: `Bearer ${token}`,
102
+ Accept: 'application/json',
103
+ },
104
+ });
105
+ if (!res.ok) {
106
+ throw new Error(`Variable list failed: ${res.status}`);
107
+ }
108
+ return res.json();
109
+ };
110
+
111
+ this.acquire = async () => {
112
+ this.users += 1;
113
+ return this.ensureConnection();
114
+ };
115
+
116
+ this.release = async () => {
117
+ this.users = Math.max(0, this.users - 1);
118
+ if (this.users === 0 && this.nc) {
119
+ const nc = this.nc;
120
+ this.nc = null;
121
+ try {
122
+ await nc.drain();
123
+ }
124
+ catch (err) {
125
+ this.warn(`Fehler beim Schließen der NATS-Verbindung: ${err.message}`);
126
+ }
127
+ }
128
+ };
129
+
130
+ this.on('close', (done) => {
131
+ this.release().finally(done);
132
+ });
133
+ }
134
+
135
+ if (!adminRoutesRegistered) {
136
+ adminRoutesRegistered = true;
137
+ RED.httpAdmin.get('/uos/providers/:id', async (req, res) => {
138
+ const node = RED.nodes.getNode(req.params.id);
139
+ if (!node) {
140
+ res.status(404).json({ error: 'config not found' });
141
+ return;
142
+ }
143
+ try {
144
+ const providers = await node.fetchProviders();
145
+ res.json(providers);
146
+ }
147
+ catch (err) {
148
+ res.status(500).json({ error: err.message });
149
+ }
150
+ });
151
+ RED.httpAdmin.get('/uos/providers/:id/:providerId/variables', async (req, res) => {
152
+ const node = RED.nodes.getNode(req.params.id);
153
+ if (!node) {
154
+ res.status(404).json({ error: 'config not found' });
155
+ return;
156
+ }
157
+ try {
158
+ const vars = await node.fetchProviderVariables(req.params.providerId);
159
+ res.json(vars);
160
+ }
161
+ catch (err) {
162
+ res.status(500).json({ error: err.message });
163
+ }
164
+ });
165
+ }
166
+
167
+ RED.nodes.registerType('uos-config', UosConfigNode, {
168
+ credentials: {
169
+ clientId: { type: 'text' },
170
+ clientSecret: { type: 'password' },
171
+ },
172
+ });
173
+ };
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "node-red-contrib-uos-nats",
3
+ "version": "0.1.0",
4
+ "description": "Node-RED nodes for u-OS Data Hub via NATS",
5
+ "license": "MIT",
6
+ "main": "nodes/uos-provider.js",
7
+ "keywords": [
8
+ "node-red",
9
+ "nats",
10
+ "uos",
11
+ "weidmueller"
12
+ ],
13
+ "dependencies": {
14
+ "flatbuffers": "^25.9.23",
15
+ "nats": "^2.19.0",
16
+ "node-fetch": "^2.6.7"
17
+ },
18
+ "node-red": {
19
+ "nodes": {
20
+ "uos-config": "nodes/uos-config.js",
21
+ "datahub-input": "nodes/datahub-input.js",
22
+ "datahub-output": "nodes/datahub-output.js"
23
+ }
24
+ }
25
+ }