homebridge-smartsystem 6.8.5 → 6.8.7
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 +2 -0
- package/package.json +1 -1
- package/server/proxy.js +33 -15
- package/server/proxy.ts +41 -18
package/README.md
CHANGED
|
@@ -309,6 +309,8 @@ Homebridge UI version
|
|
|
309
309
|
- 3: remember request before the login kicked in (and redirect to that one, once the login was succesful)
|
|
310
310
|
- 4: now using only TCP sockets to the server
|
|
311
311
|
- 5: making it more robust / inline with repo-service version
|
|
312
|
+
- 6: removed double error handlers on cloudSocket
|
|
313
|
+
- 7: restart if no free connections
|
|
312
314
|
|
|
313
315
|
## Hardware
|
|
314
316
|
A Raspberry Pi that connects to a Duotecno IP Node
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-smartsystem",
|
|
3
3
|
"displayname": "Duotecno Bridge",
|
|
4
|
-
"version": "6.8.
|
|
4
|
+
"version": "6.8.7",
|
|
5
5
|
"description": "SmartServer (Proxy TCP sockets to the cloud, Smappee MQTT, Duotecno IP Nodes, Homekit interface)",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"author": "Johan Coppieters",
|
package/server/proxy.js
CHANGED
|
@@ -38,6 +38,7 @@ catch (e) {
|
|
|
38
38
|
setProxyConfig();
|
|
39
39
|
console.log("No config-proxy.json found, using default values from homebridge or other.");
|
|
40
40
|
}
|
|
41
|
+
let connectionChecker = null;
|
|
41
42
|
const gCloudConnections = [];
|
|
42
43
|
const kDebug = config.debug || false; // enable debug mode from config
|
|
43
44
|
/////////////
|
|
@@ -60,13 +61,23 @@ function error(str) {
|
|
|
60
61
|
///////////////////////////////
|
|
61
62
|
// Start up the proxy server //
|
|
62
63
|
///////////////////////////////
|
|
63
|
-
|
|
64
|
-
makeNewCloudConnection(config.masterAddress, config.masterPort, config.cloudServer, config.cloudPort, config.uniqueId);
|
|
65
|
-
}
|
|
64
|
+
cleanStart(true);
|
|
66
65
|
function makeNewCloudConnection(master, masterPort, server, serverPort, uniqueId, count = 0) {
|
|
66
|
+
// retry making a cloud connection
|
|
67
|
+
function reconnect(err) {
|
|
68
|
+
error(`[PROXY] → [CLOUD] Failed to connect ${count + 1} times to the Cloud server: ${err.message}`);
|
|
69
|
+
if (count < 3) {
|
|
70
|
+
setTimeout(() => {
|
|
71
|
+
makeNewCloudConnection(master, masterPort, server, serverPort, uniqueId, count + 1);
|
|
72
|
+
}, 1000);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
67
75
|
const cloudSocket = new net.Socket();
|
|
76
|
+
cloudSocket.once('error', reconnect);
|
|
77
|
+
log(`[PROXY] → [CLOUD] Attempt ${count + 1} to start a new free connection for ${config.uniqueId} to the Cloud at ${server}:${serverPort}`);
|
|
68
78
|
cloudSocket.connect(serverPort, server, () => {
|
|
69
79
|
log(`[PROXY] → [CLOUD] Connected to Cloud at ${server}:${serverPort}`);
|
|
80
|
+
cloudSocket.removeListener('error', reconnect);
|
|
70
81
|
// Send unique ID as the first message to identify this proxy/device
|
|
71
82
|
cloudSocket.write(`[${uniqueId}]`);
|
|
72
83
|
debug(`[PROXY] → [CLOUD] Sent unique ID: ${uniqueId}`);
|
|
@@ -74,27 +85,32 @@ function makeNewCloudConnection(master, masterPort, server, serverPort, uniqueId
|
|
|
74
85
|
gCloudConnections.push(context);
|
|
75
86
|
log(`[PROXY] → [CLOUD] New free connection #${gCloudConnections.length} to the Cloud at ${server}:${serverPort}`);
|
|
76
87
|
});
|
|
77
|
-
cloudSocket.on('error', (err) => {
|
|
78
|
-
error(`[PROXY] → [CLOUD] Failed to connect ${count + 1} times to the Cloud server: ${err.message}`);
|
|
79
|
-
if (count < 3) {
|
|
80
|
-
setTimeout(() => {
|
|
81
|
-
makeNewCloudConnection(master, masterPort, server, serverPort, uniqueId, count + 1);
|
|
82
|
-
}, 1000);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
log(`[PROXY] → [CLOUD] Attempt ${count + 1} to start a new free connection for ${config.uniqueId} to the Cloud at ${server}:${serverPort}`);
|
|
86
88
|
}
|
|
87
89
|
exports.makeNewCloudConnection = makeNewCloudConnection;
|
|
88
90
|
////////////////
|
|
89
91
|
// Restarting //
|
|
90
92
|
////////////////
|
|
91
93
|
function cleanStart(restart = false) {
|
|
92
|
-
gCloudConnections.
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
if (gCloudConnections.length) {
|
|
95
|
+
gCloudConnections.forEach(ctx => ctx.cleanupSockets());
|
|
96
|
+
log(`[PROXY] → [CLOUD] Cleaned up all ${gCloudConnections.length} cloud connections.`);
|
|
97
|
+
gCloudConnections.splice(0, gCloudConnections.length); // clear the array
|
|
98
|
+
}
|
|
99
|
+
if (connectionChecker) {
|
|
100
|
+
clearInterval(connectionChecker);
|
|
101
|
+
connectionChecker = null;
|
|
102
|
+
}
|
|
95
103
|
if (restart) {
|
|
96
104
|
if (config.uniqueId) {
|
|
97
105
|
makeNewCloudConnection(config.masterAddress, config.masterPort, config.cloudServer, config.cloudPort, config.uniqueId);
|
|
106
|
+
// check every 5 second for a free connection
|
|
107
|
+
connectionChecker = setInterval(() => {
|
|
108
|
+
const freeConnection = gCloudConnections.find((ctx) => (!ctx.deviceSocket) && ctx.cloudSocket && (ctx.cloudSocket.readyState === 'open'));
|
|
109
|
+
if (!freeConnection) {
|
|
110
|
+
error(`[PROXY] → [CLOUD] No free connections available, restarting proxy. ***************************`);
|
|
111
|
+
cleanStart(true);
|
|
112
|
+
}
|
|
113
|
+
}, 5000);
|
|
98
114
|
}
|
|
99
115
|
else {
|
|
100
116
|
log(`[PROXY] → [CLOUD] Not restarting, no unique ID configured, not starting the proxy.`);
|
|
@@ -293,6 +309,8 @@ function restart() {
|
|
|
293
309
|
// Graceful shutdown handler
|
|
294
310
|
function handleShutdown(signal) {
|
|
295
311
|
log(`[PROXY] → [SYSTEM] Received ${signal}, shutting down gracefully...`);
|
|
312
|
+
if (connectionChecker)
|
|
313
|
+
clearInterval(connectionChecker);
|
|
296
314
|
// Close all cloud connections
|
|
297
315
|
gCloudConnections.forEach(ctx => ctx.cleanupSockets());
|
|
298
316
|
gCloudConnections.splice(0, gCloudConnections.length);
|
package/server/proxy.ts
CHANGED
|
@@ -51,6 +51,7 @@ try {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
|
|
54
|
+
let connectionChecker: NodeJS.Timer | null = null;
|
|
54
55
|
|
|
55
56
|
const gCloudConnections: Array<Context> = [];
|
|
56
57
|
const kDebug = config.debug || false; // enable debug mode from config
|
|
@@ -77,16 +78,28 @@ function error(str: string) {
|
|
|
77
78
|
///////////////////////////////
|
|
78
79
|
// Start up the proxy server //
|
|
79
80
|
///////////////////////////////
|
|
80
|
-
|
|
81
|
-
makeNewCloudConnection(config.masterAddress, config.masterPort, config.cloudServer, config.cloudPort, config.uniqueId);
|
|
82
|
-
}
|
|
81
|
+
cleanStart(true);
|
|
83
82
|
|
|
84
83
|
|
|
85
84
|
export function makeNewCloudConnection(master: string, masterPort: number, server: string, serverPort: number, uniqueId: string, count = 0) {
|
|
85
|
+
// retry making a cloud connection
|
|
86
|
+
function reconnect(err: Error) {
|
|
87
|
+
error(`[PROXY] → [CLOUD] Failed to connect ${count+1} times to the Cloud server: ${err.message}`);
|
|
88
|
+
if (count < 3) {
|
|
89
|
+
setTimeout(() => {
|
|
90
|
+
makeNewCloudConnection(master, masterPort, server, serverPort, uniqueId, count + 1);
|
|
91
|
+
}, 1000);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
86
95
|
const cloudSocket = new net.Socket();
|
|
87
|
-
|
|
96
|
+
cloudSocket.once('error', reconnect);
|
|
97
|
+
|
|
98
|
+
log(`[PROXY] → [CLOUD] Attempt ${count+1} to start a new free connection for ${config.uniqueId} to the Cloud at ${server}:${serverPort}`);
|
|
99
|
+
|
|
88
100
|
cloudSocket.connect(serverPort, server, () => {
|
|
89
101
|
log(`[PROXY] → [CLOUD] Connected to Cloud at ${server}:${serverPort}`);
|
|
102
|
+
cloudSocket.removeListener('error', reconnect);
|
|
90
103
|
|
|
91
104
|
// Send unique ID as the first message to identify this proxy/device
|
|
92
105
|
cloudSocket.write(`[${uniqueId}]`);
|
|
@@ -96,17 +109,6 @@ export function makeNewCloudConnection(master: string, masterPort: number, serve
|
|
|
96
109
|
gCloudConnections.push(context);
|
|
97
110
|
log(`[PROXY] → [CLOUD] New free connection #${gCloudConnections.length} to the Cloud at ${server}:${serverPort}`);
|
|
98
111
|
});
|
|
99
|
-
|
|
100
|
-
cloudSocket.on('error', (err) => {
|
|
101
|
-
error(`[PROXY] → [CLOUD] Failed to connect ${count+1} times to the Cloud server: ${err.message}`);
|
|
102
|
-
if (count < 3) {
|
|
103
|
-
setTimeout(() => {
|
|
104
|
-
makeNewCloudConnection(master, masterPort, server, serverPort, uniqueId, count + 1);
|
|
105
|
-
}, 1000);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
log(`[PROXY] → [CLOUD] Attempt ${count+1} to start a new free connection for ${config.uniqueId} to the Cloud at ${server}:${serverPort}`);
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
|
|
@@ -114,14 +116,33 @@ export function makeNewCloudConnection(master: string, masterPort: number, serve
|
|
|
114
116
|
// Restarting //
|
|
115
117
|
////////////////
|
|
116
118
|
export function cleanStart(restart: boolean = false) {
|
|
117
|
-
gCloudConnections.
|
|
118
|
-
|
|
119
|
+
if (gCloudConnections.length) {
|
|
120
|
+
gCloudConnections.forEach(ctx => ctx.cleanupSockets());
|
|
121
|
+
log(`[PROXY] → [CLOUD] Cleaned up all ${gCloudConnections.length} cloud connections.`);
|
|
119
122
|
|
|
120
|
-
|
|
123
|
+
gCloudConnections.splice(0, gCloudConnections.length); // clear the array
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (connectionChecker) {
|
|
127
|
+
clearInterval(connectionChecker);
|
|
128
|
+
connectionChecker = null;
|
|
129
|
+
}
|
|
121
130
|
|
|
122
131
|
if (restart) {
|
|
123
132
|
if (config.uniqueId) {
|
|
124
133
|
makeNewCloudConnection(config.masterAddress, config.masterPort, config.cloudServer, config.cloudPort, config.uniqueId);
|
|
134
|
+
|
|
135
|
+
// check every 5 second for a free connection
|
|
136
|
+
connectionChecker = setInterval(() => {
|
|
137
|
+
const freeConnection = gCloudConnections.find((ctx: Context) =>
|
|
138
|
+
(!ctx.deviceSocket) && ctx.cloudSocket && (ctx.cloudSocket.readyState === 'open')
|
|
139
|
+
);
|
|
140
|
+
if (!freeConnection) {
|
|
141
|
+
error(`[PROXY] → [CLOUD] No free connections available, restarting proxy. ***************************`);
|
|
142
|
+
cleanStart(true);
|
|
143
|
+
}
|
|
144
|
+
}, 5000);
|
|
145
|
+
|
|
125
146
|
} else {
|
|
126
147
|
log(`[PROXY] → [CLOUD] Not restarting, no unique ID configured, not starting the proxy.`);
|
|
127
148
|
}
|
|
@@ -364,6 +385,8 @@ function restart() {
|
|
|
364
385
|
function handleShutdown(signal: string) {
|
|
365
386
|
log(`[PROXY] → [SYSTEM] Received ${signal}, shutting down gracefully...`);
|
|
366
387
|
|
|
388
|
+
if (connectionChecker)clearInterval(connectionChecker);
|
|
389
|
+
|
|
367
390
|
// Close all cloud connections
|
|
368
391
|
gCloudConnections.forEach(ctx => ctx.cleanupSockets());
|
|
369
392
|
gCloudConnections.splice(0, gCloudConnections.length);
|