node-red-contrib-remote 1.4.0 → 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 +8 -1
- package/nodes/locales/de/remote-access.json +2 -1
- package/nodes/locales/de/remote-config.json +1 -0
- package/nodes/locales/en-US/remote-access.json +2 -1
- package/nodes/locales/en-US/remote-config.json +1 -0
- package/nodes/remote-access.html +2 -4
- package/nodes/remote-access.js +29 -8
- package/nodes/remote-commons.js +22 -1
- package/nodes/remote-config.html +4 -0
- package/nodes/remote-config.js +7 -1
- package/nodes/remote-notification.js +6 -2
- package/nodes/remote-question.js +6 -2
- 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,13 @@ 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
|
+
|
|
39
46
|
Version 1.4.0
|
|
40
47
|
- In addition to the QR code, a link is now generated to add an instance in the app.
|
|
41
48
|
- Sending notifications and questions is prevented if msg.playload.send === false.
|
|
@@ -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.",
|
|
@@ -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.",
|
package/nodes/remote-access.html
CHANGED
|
@@ -8,10 +8,8 @@
|
|
|
8
8
|
verbose: {value:0}
|
|
9
9
|
},
|
|
10
10
|
inputs: 0,
|
|
11
|
-
outputs:
|
|
12
|
-
outputLabels: ["action output"],
|
|
13
|
-
// outputs: 2,
|
|
14
|
-
// outputLabels: ["action output", "geofence output"],
|
|
11
|
+
outputs: 2,
|
|
12
|
+
outputLabels: ["action output", "geofence output"],
|
|
15
13
|
icon: "font-awesome/fa-mobile",
|
|
16
14
|
label: function() {
|
|
17
15
|
return this.name || "remote access";
|
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
|
}
|
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
|
}
|
|
@@ -214,6 +217,7 @@
|
|
|
214
217
|
<select id="node-config-input-region">
|
|
215
218
|
<option value="us" data-i18n="remote-config.label.region_us"></option>
|
|
216
219
|
<option value="de" data-i18n="remote-config.label.region_de"></option>
|
|
220
|
+
<option value="sg" data-i18n="remote-config.label.region_sg"></option>
|
|
217
221
|
<!-- <option value="dev" data-i18n="remote-config.label.region_dev"></option> -->
|
|
218
222
|
</select>
|
|
219
223
|
</div>
|
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
|
});
|
|
@@ -97,6 +100,9 @@ module.exports = function(RED) {
|
|
|
97
100
|
if ( error.response && error.response.data && error.response.data.message ) {
|
|
98
101
|
errorMessage = errorMessage + " / " + error.response.data.message;
|
|
99
102
|
}
|
|
103
|
+
if ( commons.getNetworkErrorCustomString(error) !== undefined) {
|
|
104
|
+
errorMessage = commons.getNetworkErrorCustomString(error);
|
|
105
|
+
}
|
|
100
106
|
res.json({ 'error': errorMessage });
|
|
101
107
|
});
|
|
102
108
|
});
|
|
@@ -18,7 +18,7 @@ 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.send === false) {
|
|
21
|
+
if (msg.payload !== undefined && msg.payload.send === false) {
|
|
22
22
|
node.log(`Notification not send (msg.payload.send = false).`)
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
@@ -63,7 +63,11 @@ module.exports = function(RED) {
|
|
|
63
63
|
}
|
|
64
64
|
})
|
|
65
65
|
.catch((error) => {
|
|
66
|
-
|
|
66
|
+
// Log error
|
|
67
|
+
node.error('sendNotification: ' + commons.getNetworkErrorString(error))
|
|
68
|
+
if ( commons.getNetworkErrorCustomString(error) !== undefined) {
|
|
69
|
+
node.error(commons.getNetworkErrorCustomString(error));
|
|
70
|
+
}
|
|
67
71
|
|
|
68
72
|
// Output status if configured so
|
|
69
73
|
if ( config.output == 2 ) {
|
package/nodes/remote-question.js
CHANGED
|
@@ -18,7 +18,7 @@ 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.send === false) {
|
|
21
|
+
if (msg.payload !== undefined && msg.payload.send === false) {
|
|
22
22
|
node.log(`Question not send (msg.payload.send = false).`)
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
@@ -77,7 +77,11 @@ module.exports = function(RED) {
|
|
|
77
77
|
node.debug(`Question send successfull`)
|
|
78
78
|
})
|
|
79
79
|
.catch((error) => {
|
|
80
|
-
|
|
80
|
+
// Log error
|
|
81
|
+
node.error('sendNotification: ' + commons.getNetworkErrorString(error))
|
|
82
|
+
if ( commons.getNetworkErrorCustomString(error) !== undefined) {
|
|
83
|
+
node.error(commons.getNetworkErrorCustomString(error));
|
|
84
|
+
}
|
|
81
85
|
|
|
82
86
|
// Output Error
|
|
83
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": {
|