node-red-contrib-remote 1.3.3 → 1.5.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.
- package/README.md +13 -1
- package/nodes/locales/de/remote-access.json +2 -1
- package/nodes/locales/de/remote-config.json +6 -0
- package/nodes/locales/de/remote-notification.json +1 -1
- package/nodes/locales/de/remote-question.json +1 -1
- package/nodes/locales/en-US/remote-access.json +2 -1
- package/nodes/locales/en-US/remote-config.json +6 -0
- package/nodes/locales/en-US/remote-notification.json +1 -1
- package/nodes/locales/en-US/remote-question.json +1 -1
- package/nodes/remote-access.html +2 -2
- package/nodes/remote-access.js +67 -12
- package/nodes/remote-commons.js +22 -1
- package/nodes/remote-config.html +10 -0
- package/nodes/remote-config.js +10 -2
- package/nodes/remote-notification.js +14 -4
- package/nodes/remote-question.js +14 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Remote-RED
|
|
2
2
|
|
|
3
|
-
Remote-RED is an ecosystem to bring remote access and
|
|
3
|
+
Remote-RED is an ecosystem to bring remote access, push notification and geofencing to Node-RED. There are also additional functions like directly answer on a notification and homescreen widgets. It consists of several parts:
|
|
4
4
|
- node-red-contrib-remote: The Node-RED nodes of Remote-RED. Published in this repro.
|
|
5
5
|
- Remote-RED servers: Several servers used for proxying the remote access traffic and sending push notifications.
|
|
6
6
|
- Remote-RED apps: Apps to access the services published by the Remote-RED remote-access node and receiving the push notifications of the remote-notification node. Available or Android, iOS and iPadOS.
|
|
@@ -36,6 +36,18 @@ You will find more information on [www.remote-red-com](https://www.remote-red.co
|
|
|
36
36
|
|
|
37
37
|
## Version History
|
|
38
38
|
|
|
39
|
+
Version 1.5.0
|
|
40
|
+
- Geofencing! You can add geofences in the apps. Entering and leaving them will trigger a message on the new output of the remote access node.
|
|
41
|
+
- Adding server location in Asia.
|
|
42
|
+
- New instances will have the base url '/ui' again.
|
|
43
|
+
- Error with "Multiple requests" after a missing internet connection fixed.
|
|
44
|
+
- iOS App: Links with target '_blank' will be redirected to iOS.
|
|
45
|
+
|
|
46
|
+
Version 1.4.0
|
|
47
|
+
- In addition to the QR code, a link is now generated to add an instance in the app.
|
|
48
|
+
- Sending notifications and questions is prevented if msg.playload.send === false.
|
|
49
|
+
- Error catched if a notification or question does not contain a title and body.
|
|
50
|
+
|
|
39
51
|
Version 1.3.3:
|
|
40
52
|
- Improved compatibility for Windows.
|
|
41
53
|
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"commerror": "Fehler bei der Kommunikation mit dem Server.",
|
|
18
18
|
"noconfig": "Keine Konfiguration gefunden.",
|
|
19
19
|
"incompleteconfig": "Konfiguration unvollständig.",
|
|
20
|
-
"backupconfig": "Konfiguration aus Backup."
|
|
20
|
+
"backupconfig": "Konfiguration aus Backup.",
|
|
21
|
+
"banned": "Die Instanz wurde deaktiviert. Möglicherweise aufgrund einer DDOS-Attacke. Wenn Sie dieses System nicht missbrauchen, erstelle bitte eine neuen Konfig Node, um Remote-RED wieder zu verwenden. Andernfalls suchen Sie nach falschen Weiterleitungen oder Proxy Fehlern. Diese IP wird für 10 Minuten gesperrt."
|
|
21
22
|
},
|
|
22
23
|
"help": {
|
|
23
24
|
"title": "Hilfe",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"region": "Standort Server",
|
|
13
13
|
"region_us": "Amerika (USA)",
|
|
14
14
|
"region_de": "Europa (Deutschland)",
|
|
15
|
+
"region_sg": "Asien (Singapur)",
|
|
15
16
|
"region_dev": "Entwicklung",
|
|
16
17
|
"region_desc": "Der Standort kann nicht mehr geändert werden, sobald eine App registriert wurde.",
|
|
17
18
|
"change_info": "Wenn Du Einstellungen änderst, musst Du die App neu verbinden.",
|
|
@@ -46,6 +47,11 @@
|
|
|
46
47
|
"apphelp": {
|
|
47
48
|
"title": "App Hilfe",
|
|
48
49
|
"para1": "Lade die Remote-RED App aus dem Apple AppStore oder Google PlayStore herunter. Verwende in der App die Funktion “Node-RED Instanz hinzufügen” um diesen QR-Code zu scannen."
|
|
50
|
+
},
|
|
51
|
+
"applink": {
|
|
52
|
+
"title": "Alternative: Per Link hinzufügen",
|
|
53
|
+
"para1": "Öffne diesen Link auf Deinem iOS oder Android Gerät, nachdem Du die Remote-RED App installiert hast:",
|
|
54
|
+
"link": "Link zum hinzufügen"
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
}
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"title": "Hilfe",
|
|
35
35
|
"para1": "Über diese Node kannst Du eine Push Notification an die Geräte versenden, die mit der gewählten Config-Node verbunden sind. Wähle hierzu eine Config-Node, die Du auch z.B. bereits in einer Access-Node verwendest. Du kannst in mehreren Notification-Nodes die selbe Config-Node verwenden.",
|
|
36
36
|
"para2": "Konfiguriere den Titel und den Text der Benachrichtigung. Die Vorgabewerte gehen davon aus, das im Payload der eingehenden Nachricht die Strings “title” und “body” enthalten sind. Du kannst aber auch feste Texte eingeben oder Flow- bzw. Global-Variablen verwenden.",
|
|
37
|
-
"para3": "Immer sobald eine Message bei der Notification-Node ankommt, wird eine Notification an Deine Geräte versendet."
|
|
37
|
+
"para3": "Immer sobald eine Message bei der Notification-Node ankommt, wird eine Notification an Deine Geräte versendet. Es wird kein Versand durchgeführt, wenn msg.payload.send den Boolean-Wert 'false' enthält."
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"para2": "Wichtig ist, das die Confg-Node auf Deinen lokalen Node-RED Rechner verweist und eine Access-Node damit aktiv ist. Die Basis URL ist dabei irrelevant.",
|
|
39
39
|
"para3": "Konfiguriere den Titel und den Text der Benachrichtigung. Die Vorgabewerte gehen davon aus, das im Payload der eingehenden Nachricht die Strings “title” und “body” enthalten sind. Du kannst aber auch feste Texte eingeben oder Flow- bzw. Global-Variablen verwenden.",
|
|
40
40
|
"para4": "Du kannst bis zu drei Antworten vorgeben. Der Text der Antworten kannst Du direkt als String eingeben oder aus der eingehenden Nachricht übernehmen. Ist der Text leer, wird die Antwort nicht angezeigt. Über den Wert kannst Du angeben, was die Node per msg.payload ausgibt, wenn Du diese Antwort wählst.",
|
|
41
|
-
"para5": "Immer sobald eine Message bei der Question-Node ankommt, wird eine Notification an Deine Geräte versendet."
|
|
41
|
+
"para5": "Immer sobald eine Message bei der Question-Node ankommt, wird eine Notification an Deine Geräte versendet. Es wird kein Versand durchgeführt, wenn msg.payload.send den Boolean-Wert 'false' enthält."
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"commerror": "Error communicating with server.",
|
|
18
18
|
"noconfig": "No configuration found.",
|
|
19
19
|
"incompleteconfig": "Configuration incomplete.",
|
|
20
|
-
"backupconfig": "Configuration from backup."
|
|
20
|
+
"backupconfig": "Configuration from backup.",
|
|
21
|
+
"banned": "Instance is deactivated. Maybe due DDOS attacks. If you are not missusing this system, please create new config node to use Remote-RED again. Otherwise look for incorrect redirects or such errors. Banning IP for 10 minutes."
|
|
21
22
|
},
|
|
22
23
|
"help": {
|
|
23
24
|
"title": "Help",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"region": "Server location",
|
|
13
13
|
"region_us": "America (USA)",
|
|
14
14
|
"region_de": "Europe (Germany)",
|
|
15
|
+
"region_sg": "Asia (Singapur)",
|
|
15
16
|
"region_dev": "Development host",
|
|
16
17
|
"region_desc": "The region can´t be changed after registering an app.",
|
|
17
18
|
"change_info": "If you change settings, you need to reconnect the app.",
|
|
@@ -46,6 +47,11 @@
|
|
|
46
47
|
"apphelp": {
|
|
47
48
|
"title": "App Help",
|
|
48
49
|
"para1": "Download the Remote-RED app from the Apple AppStore or Google PlayStore. Use the function “Add Node-RED Instance” in the app to scan this QR Code."
|
|
50
|
+
},
|
|
51
|
+
"applink": {
|
|
52
|
+
"title": "Alternative: Add via link",
|
|
53
|
+
"para1": "Open this link on your iOS or Android device after installing the Remote-RED app:",
|
|
54
|
+
"link": "Link to add"
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
}
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"title": "Help",
|
|
35
35
|
"para1": "With this node you can send a push notification to the devices connected to the selected config node. Select a config node that you already use in an access node. You can use the same config node in several notification nodes.",
|
|
36
36
|
"para2": "Configure the title and the text of the notification. The default values assume that the payload of the incoming message contains the strings “title” and “body”. You can also enter fixed texts or use flow or global variables.",
|
|
37
|
-
"para3": "Whenever a message arrives at the notification node, a notification is sent to your devices."
|
|
37
|
+
"para3": "Whenever a message arrives at the notification node, a notification is sent to your devices. No send is performed if msg.payload.send contains the boolean value 'false'."
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"para2": "It is important that the confg node points to your local Node-RED computer and that an access node is active with it. The base URL is irrelevant.",
|
|
39
39
|
"para3": "Configure the title and the text of the notification. The default values assume that the payload of the incoming message contains the strings “title” and “body”. You can also enter fixed texts or use flow or global variables.",
|
|
40
40
|
"para4": "You can specify up to three answers. The text of the answers can be entered directly as an string or taken from the incoming message. If the text is empty, the answer is not displayed. You can use the value to specify what the node outputs in msg.payload when you select this answer.",
|
|
41
|
-
"para5": "Whenever a message arrives at the question node, a notification is sent to your devices."
|
|
41
|
+
"para5": "Whenever a message arrives at the question node, a notification is sent to your devices. No send is performed if msg.payload.send contains the boolean value 'false'."
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
}
|
package/nodes/remote-access.html
CHANGED
package/nodes/remote-access.js
CHANGED
|
@@ -4,6 +4,7 @@ module.exports = function(RED) {
|
|
|
4
4
|
const os = require("os");
|
|
5
5
|
let sshprocess = undefined
|
|
6
6
|
let statustext = ''
|
|
7
|
+
let instanceIsBanned = false
|
|
7
8
|
|
|
8
9
|
function startSSH(node, server, port) {
|
|
9
10
|
try {
|
|
@@ -18,7 +19,7 @@ module.exports = function(RED) {
|
|
|
18
19
|
if ( host === 'localhost' && os.platform() === 'win32' ) {
|
|
19
20
|
host = '127.0.0.1'
|
|
20
21
|
}
|
|
21
|
-
//node.log('ssh -o StrictHostKeyChecking=no -R ' + port.toString() + ':' + host + ':' + node.confignode.port.toString() + ' forward@proxy-' + server + ' -N');
|
|
22
|
+
// node.log('ssh -o StrictHostKeyChecking=no -R ' + port.toString() + ':' + host + ':' + node.confignode.port.toString() + ' forward@proxy-' + server + ' -N');
|
|
22
23
|
var sshparameters = ['-o StrictHostKeyChecking=no', '-R', port.toString() + ':' + host + ':' + node.confignode.port.toString(), 'forward@proxy-' + server, '-N'];
|
|
23
24
|
if ( node.verbose ) {
|
|
24
25
|
sshparameters.push('-v');
|
|
@@ -36,6 +37,9 @@ module.exports = function(RED) {
|
|
|
36
37
|
|
|
37
38
|
sshprocess.stderr.on('data', (data) => {
|
|
38
39
|
logSSHBuffer(node, data, 'ssh process stderr');
|
|
40
|
+
if ( data.toString().includes('Connection timed out')) {
|
|
41
|
+
node.error(`SSH connection timeout. Please check if port 22 is open for outgoing connections.`);
|
|
42
|
+
}
|
|
39
43
|
});
|
|
40
44
|
|
|
41
45
|
sshprocess.on('close', (code, signal) => {
|
|
@@ -89,6 +93,11 @@ module.exports = function(RED) {
|
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
function requestInstanceSlot(node) {
|
|
96
|
+
// Is this instance banned?
|
|
97
|
+
if ( instanceIsBanned ) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
92
101
|
// Call API to retrive server and port.
|
|
93
102
|
const axiosInstance = commons.createAxiosInstance();
|
|
94
103
|
axiosInstance.post(`https://api-${node.confignode.server}/instanceSlotRequest`, {
|
|
@@ -105,10 +114,22 @@ module.exports = function(RED) {
|
|
|
105
114
|
startSSH(node, node.confignode.server, port);
|
|
106
115
|
})
|
|
107
116
|
.catch((error) => {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
117
|
+
// Log error
|
|
118
|
+
node.error('requestInstanceSlot: ' + commons.getNetworkErrorString(error))
|
|
119
|
+
if ( commons.getNetworkErrorCustomString(error) !== undefined) {
|
|
120
|
+
node.error(commons.getNetworkErrorCustomString(error));
|
|
111
121
|
}
|
|
122
|
+
|
|
123
|
+
// Wenn gebannt -> Merken
|
|
124
|
+
if ( error.response && error.response.status ) {
|
|
125
|
+
if ( error.response.status === 403 ) {
|
|
126
|
+
setStatus(node, {fill:"red",shape:"dot",text:"remote-access.status.banned"});
|
|
127
|
+
instanceIsBanned = true;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Set status
|
|
112
133
|
setStatus(node, {fill:"red",shape:"dot",text:"remote-access.status.commerror"});
|
|
113
134
|
return;
|
|
114
135
|
});
|
|
@@ -183,10 +204,10 @@ module.exports = function(RED) {
|
|
|
183
204
|
}
|
|
184
205
|
})
|
|
185
206
|
.catch((error) => {
|
|
186
|
-
// Error on api call >
|
|
187
|
-
node.error('heartbeat: ' + error)
|
|
188
|
-
if (
|
|
189
|
-
node.error(
|
|
207
|
+
// Error on api call > Log error
|
|
208
|
+
node.error('heartbeat: ' + commons.getNetworkErrorString(error))
|
|
209
|
+
if ( commons.getNetworkErrorCustomString(error) !== undefined) {
|
|
210
|
+
node.error(commons.getNetworkErrorCustomString(error));
|
|
190
211
|
}
|
|
191
212
|
});
|
|
192
213
|
}
|
|
@@ -231,8 +252,8 @@ module.exports = function(RED) {
|
|
|
231
252
|
tryConnect(node);
|
|
232
253
|
|
|
233
254
|
// Post URL for action
|
|
234
|
-
const
|
|
235
|
-
RED.httpNode.post(
|
|
255
|
+
const postUrlAction = `/contrib-remote/action/${node.confignode.instancehash}`;
|
|
256
|
+
RED.httpNode.post(postUrlAction, function(req,res) {
|
|
236
257
|
// Output action as new message
|
|
237
258
|
node.log(`Action '${req.body.action}' received value '${req.body.value}'`);
|
|
238
259
|
const msg = {
|
|
@@ -242,7 +263,28 @@ module.exports = function(RED) {
|
|
|
242
263
|
"value": req.body.value
|
|
243
264
|
}
|
|
244
265
|
}
|
|
245
|
-
node.send(msg);
|
|
266
|
+
node.send([msg, null]);
|
|
267
|
+
|
|
268
|
+
// Send OK to app
|
|
269
|
+
const responseData = {
|
|
270
|
+
'status': 'OK'
|
|
271
|
+
};
|
|
272
|
+
res.json(responseData);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// Post URL for geofence
|
|
276
|
+
const postUrlGeofence = `/contrib-remote/geofence/${node.confignode.instancehash}`;
|
|
277
|
+
RED.httpNode.post(postUrlGeofence, function(req,res) {
|
|
278
|
+
// Output action as new message
|
|
279
|
+
node.log(`Geofence '${req.body.name}' received enter value '${req.body.enter}'`);
|
|
280
|
+
const msg = {
|
|
281
|
+
"_msgid": RED.util.generateId(),
|
|
282
|
+
"payload": {
|
|
283
|
+
"name": req.body.name,
|
|
284
|
+
"enter": req.body.enter
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
node.send([null, msg]);
|
|
246
288
|
|
|
247
289
|
// Send OK to app
|
|
248
290
|
const responseData = {
|
|
@@ -271,7 +313,20 @@ module.exports = function(RED) {
|
|
|
271
313
|
|
|
272
314
|
// Remove old routes, without a new deploy would break it..
|
|
273
315
|
RED.httpNode._router.stack.forEach(function(route,i,routes) {
|
|
274
|
-
if (route.route &&
|
|
316
|
+
if (route.route && route.route.path === postUrlAction) {
|
|
317
|
+
node.log(` -> Remove Route '${route.route.path}'`);
|
|
318
|
+
routes.splice(i,1);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
RED.httpNode._router.stack.forEach(function(route,i,routes) {
|
|
322
|
+
if (route.route && route.route.path === postUrlGeofence) {
|
|
323
|
+
node.log(` -> Remove Route '${route.route.path}'`);
|
|
324
|
+
routes.splice(i,1);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
RED.httpNode._router.stack.forEach(function(route,i,routes) {
|
|
328
|
+
if (route.route && route.route.path === getUrl) {
|
|
329
|
+
node.log(` -> Remove Route '${route.route.path}'`);
|
|
275
330
|
routes.splice(i,1);
|
|
276
331
|
}
|
|
277
332
|
});
|
package/nodes/remote-commons.js
CHANGED
|
@@ -17,7 +17,7 @@ module.exports = {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
});
|
|
20
|
-
return axios.create({ httpsAgent: httpsAgent });
|
|
20
|
+
return axios.create({ httpsAgent: httpsAgent, timeout: 5000 });
|
|
21
21
|
},
|
|
22
22
|
|
|
23
23
|
getNodeVersion: function() {
|
|
@@ -35,6 +35,27 @@ module.exports = {
|
|
|
35
35
|
node.error(`Error evaluating value: ${e}`)
|
|
36
36
|
}
|
|
37
37
|
return evalValue;
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
getNetworkErrorString: function(error) {
|
|
41
|
+
// Trys to get a error message
|
|
42
|
+
let errorString = `` + error;
|
|
43
|
+
if ( error.response && error.response.data && error.response.data.message ) {
|
|
44
|
+
errorString = `${error.response.data.message}`;
|
|
45
|
+
}
|
|
46
|
+
return errorString;
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
getNetworkErrorCustomString: function(error) {
|
|
50
|
+
// Custom error messages for common errors
|
|
51
|
+
let errorString = undefined;
|
|
52
|
+
if ( error.code === 'ECONNABORTED' ) {
|
|
53
|
+
errorString = `Error during https call. Please check Internet connection on your Node-RED server. Please check if a firewall blocks outgoing port 443.`;
|
|
54
|
+
}
|
|
55
|
+
if ( error.code === 'EAI_AGAIN' ) {
|
|
56
|
+
errorString = `Error during DNS queries. Please check Internet connection on your Node-RED server. Please check if a firewall blocks your DNS queries.`;
|
|
57
|
+
}
|
|
58
|
+
return errorString;
|
|
38
59
|
}
|
|
39
60
|
|
|
40
61
|
}
|
package/nodes/remote-config.html
CHANGED
|
@@ -103,6 +103,9 @@
|
|
|
103
103
|
} else {
|
|
104
104
|
// Show error
|
|
105
105
|
alert('Error while registering instance: ' + data.error);
|
|
106
|
+
|
|
107
|
+
// Enable button again
|
|
108
|
+
document.getElementById('registerRemoteAppButton').disabled = false;
|
|
106
109
|
}
|
|
107
110
|
});
|
|
108
111
|
}
|
|
@@ -130,6 +133,7 @@
|
|
|
130
133
|
if ( data.error == undefined ) {
|
|
131
134
|
// Show QR Code
|
|
132
135
|
document.getElementById('registerRemoteAppQRCode').src = data.qrcode;
|
|
136
|
+
document.getElementById('appLink').setAttribute('href', data.link);
|
|
133
137
|
document.getElementById('registerRemoteAppQRCodeContainer').style.removeProperty('visibility');
|
|
134
138
|
document.getElementById('registerRemoteAppQRCodeContainer').style.removeProperty('height');
|
|
135
139
|
document.getElementById('registerRemoteAppButtonText').innerHTML = document.getElementById('registerRemoteAppButton_next_text').innerHTML;
|
|
@@ -213,6 +217,7 @@
|
|
|
213
217
|
<select id="node-config-input-region">
|
|
214
218
|
<option value="us" data-i18n="remote-config.label.region_us"></option>
|
|
215
219
|
<option value="de" data-i18n="remote-config.label.region_de"></option>
|
|
220
|
+
<option value="sg" data-i18n="remote-config.label.region_sg"></option>
|
|
216
221
|
<!-- <option value="dev" data-i18n="remote-config.label.region_dev"></option> -->
|
|
217
222
|
</select>
|
|
218
223
|
</div>
|
|
@@ -243,6 +248,11 @@
|
|
|
243
248
|
<label data-i18n="remote-config.apphelp.title" style="font-weight: bold;"></label>
|
|
244
249
|
<label data-i18n="remote-config.apphelp.para1"></label>
|
|
245
250
|
</div>
|
|
251
|
+
<div style="max-width: 460px; border-width: 1px; border-style: dashed; border-color: #666; padding: 10px; margin-top: 6px; margin-bottom: 20px;">
|
|
252
|
+
<label data-i18n="remote-config.applink.title" style="font-weight: bold;"></label>
|
|
253
|
+
<label data-i18n="remote-config.applink.para1"></label>
|
|
254
|
+
<a id="appLink" href="" target="_blank"><i><label data-i18n="remote-config.applink.link" style="display: inline; color: #AD1626;"></label></i></a>
|
|
255
|
+
</div>
|
|
246
256
|
</div>
|
|
247
257
|
|
|
248
258
|
<div id="remoteInstanceInputs" style="max-height: 0px;">
|
package/nodes/remote-config.js
CHANGED
|
@@ -27,7 +27,7 @@ module.exports = function(RED) {
|
|
|
27
27
|
// Return the internal IP and the mountpath
|
|
28
28
|
const ipData = {
|
|
29
29
|
'ipv4': internalIp.v4.sync(),
|
|
30
|
-
'baseurl': RED.httpNode.mountpath + ((RED.settings.ui !== undefined && RED.settings.ui.path !== undefined) ? RED.settings.ui.path : ''),
|
|
30
|
+
'baseurl': RED.httpNode.mountpath + ((RED.settings.ui !== undefined && RED.settings.ui.path !== undefined) ? RED.settings.ui.path : 'ui'),
|
|
31
31
|
'port': (RED.settings.uiPort !== undefined) ? String(RED.settings.uiPort) : '1880'
|
|
32
32
|
}
|
|
33
33
|
console.log(`${JSON.stringify(ipData)}`);
|
|
@@ -48,6 +48,9 @@ module.exports = function(RED) {
|
|
|
48
48
|
if ( error.response && error.response.data && error.response.data.message ) {
|
|
49
49
|
errorMessage = errorMessage + " / " + error.response.data.message;
|
|
50
50
|
}
|
|
51
|
+
if ( commons.getNetworkErrorCustomString(error) !== undefined) {
|
|
52
|
+
errorMessage = commons.getNetworkErrorCustomString(error);
|
|
53
|
+
}
|
|
51
54
|
res.json({ 'error': errorMessage });
|
|
52
55
|
});
|
|
53
56
|
});
|
|
@@ -82,9 +85,11 @@ module.exports = function(RED) {
|
|
|
82
85
|
const qrCodeString = JSON.stringify(qrCodeData);
|
|
83
86
|
const qrCodeStringBuffer = Buffer.from(qrCodeString);
|
|
84
87
|
const qrCodeStringBase64 = qrCodeStringBuffer.toString('base64');
|
|
88
|
+
const link = 'remotered://add?data=' + qrCodeStringBase64;
|
|
85
89
|
QRCode.toDataURL(qrCodeStringBase64, function (err, url) {
|
|
86
90
|
const responseData = {
|
|
87
|
-
'qrcode': url
|
|
91
|
+
'qrcode': url,
|
|
92
|
+
'link': link
|
|
88
93
|
}
|
|
89
94
|
res.json(responseData);
|
|
90
95
|
});
|
|
@@ -95,6 +100,9 @@ module.exports = function(RED) {
|
|
|
95
100
|
if ( error.response && error.response.data && error.response.data.message ) {
|
|
96
101
|
errorMessage = errorMessage + " / " + error.response.data.message;
|
|
97
102
|
}
|
|
103
|
+
if ( commons.getNetworkErrorCustomString(error) !== undefined) {
|
|
104
|
+
errorMessage = commons.getNetworkErrorCustomString(error);
|
|
105
|
+
}
|
|
98
106
|
res.json({ 'error': errorMessage });
|
|
99
107
|
});
|
|
100
108
|
});
|
|
@@ -18,11 +18,17 @@ module.exports = function(RED) {
|
|
|
18
18
|
// Act on incomming messages
|
|
19
19
|
node.on('input', function(msg) {
|
|
20
20
|
if (node.confignode != undefined) {
|
|
21
|
+
if (msg.payload !== undefined && msg.payload.send === false) {
|
|
22
|
+
node.log(`Notification not send (msg.payload.send = false).`)
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
21
25
|
node.limiter.removeTokens(1, function(err, remainingRequests) {
|
|
22
26
|
if (remainingRequests >= 0) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
let title = commons.evaluateValue(RED, config.notificationTitle, config.notificationTitleType, node, msg);
|
|
28
|
+
let body = commons.evaluateValue(RED, config.notificationBody, config.notificationBodyType, node, msg);
|
|
29
|
+
if (title == undefined) title = '';
|
|
30
|
+
if (body == undefined) body = '';
|
|
31
|
+
const notificationEmpty = (title == '' && body == '');
|
|
26
32
|
if (!notificationEmpty) {
|
|
27
33
|
// Title and/or body are filled
|
|
28
34
|
|
|
@@ -57,7 +63,11 @@ module.exports = function(RED) {
|
|
|
57
63
|
}
|
|
58
64
|
})
|
|
59
65
|
.catch((error) => {
|
|
60
|
-
|
|
66
|
+
// Log error
|
|
67
|
+
node.error('sendNotification: ' + commons.getNetworkErrorString(error))
|
|
68
|
+
if ( commons.getNetworkErrorCustomString(error) !== undefined) {
|
|
69
|
+
node.error(commons.getNetworkErrorCustomString(error));
|
|
70
|
+
}
|
|
61
71
|
|
|
62
72
|
// Output status if configured so
|
|
63
73
|
if ( config.output == 2 ) {
|
package/nodes/remote-question.js
CHANGED
|
@@ -18,11 +18,17 @@ module.exports = function(RED) {
|
|
|
18
18
|
// Act on incomming messages
|
|
19
19
|
node.on('input', function(msg) {
|
|
20
20
|
if (node.confignode != undefined) {
|
|
21
|
+
if (msg.payload !== undefined && msg.payload.send === false) {
|
|
22
|
+
node.log(`Question not send (msg.payload.send = false).`)
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
21
25
|
node.limiter.removeTokens(1, function(err, remainingRequests) {
|
|
22
26
|
if (remainingRequests >= 0) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
let title = commons.evaluateValue(RED, config.questionTitle, config.questionTitleType, node, msg);
|
|
28
|
+
let body = commons.evaluateValue(RED, config.questionBody, config.questionBodyType, node, msg);
|
|
29
|
+
if (title == undefined) title = '';
|
|
30
|
+
if (body == undefined) body = '';
|
|
31
|
+
const notificationEmpty = (title == '' && body == '');
|
|
26
32
|
if (!notificationEmpty) {
|
|
27
33
|
// Title and/or body are filled, generate question data
|
|
28
34
|
let questionData = {
|
|
@@ -71,7 +77,11 @@ module.exports = function(RED) {
|
|
|
71
77
|
node.debug(`Question send successfull`)
|
|
72
78
|
})
|
|
73
79
|
.catch((error) => {
|
|
74
|
-
|
|
80
|
+
// Log error
|
|
81
|
+
node.error('sendNotification: ' + commons.getNetworkErrorString(error))
|
|
82
|
+
if ( commons.getNetworkErrorCustomString(error) !== undefined) {
|
|
83
|
+
node.error(commons.getNetworkErrorCustomString(error));
|
|
84
|
+
}
|
|
75
85
|
|
|
76
86
|
// Output Error
|
|
77
87
|
const msg = {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-remote",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Remote
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "Remote-RED is an ecosystem to bring remote access, push notification and geofencing to Node-RED. There are also additional functions like directly answer on a notification and homescreen widgets.",
|
|
5
5
|
"author": "Thorsten Heilmann",
|
|
6
6
|
"license": "GPL-3.0",
|
|
7
7
|
"node-red": {
|