nodejs-poolcontroller 8.0.5 → 8.1.1
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/Changelog +15 -0
- package/README.md +10 -17
- package/anslq25/MessagesMock.ts +5 -1
- package/anslq25/boards/MockSystemBoard.ts +1 -1
- package/anslq25/chemistry/MockChlorinator.ts +32 -8
- package/app.ts +10 -2
- package/controller/Equipment.ts +15 -79
- package/controller/State.ts +4 -72
- package/controller/boards/NixieBoard.ts +1 -0
- package/controller/boards/SystemBoard.ts +5 -1
- package/controller/comms/Comms.ts +9 -8
- package/controller/comms/messages/Messages.ts +1 -1
- package/controller/nixie/chemistry/ChemController.ts +64 -31
- package/controller/nixie/circuits/Circuit.ts +66 -31
- package/logger/Logger.ts +61 -18
- package/package.json +1 -1
- package/web/Server.ts +167 -18
- package/web/services/config/Config.ts +4 -3
package/web/Server.ts
CHANGED
|
@@ -1423,18 +1423,151 @@ export class REMInterfaceServer extends ProtoServer {
|
|
|
1423
1423
|
try {
|
|
1424
1424
|
let response = await this.sendClientRequest('GET', '/config/backup/controller', undefined, 10000);
|
|
1425
1425
|
return response;
|
|
1426
|
-
} catch (err) {
|
|
1426
|
+
} catch (err) {
|
|
1427
|
+
logger.error(`Error requesting GET /config/backup/controller: ${err.message}`);
|
|
1428
|
+
let errorResponse = new InterfaceServerResponse();
|
|
1429
|
+
errorResponse.error = new Error(`Error requesting GET /config/backup/controller: ${err.message}`);
|
|
1430
|
+
return errorResponse;
|
|
1431
|
+
}
|
|
1427
1432
|
}
|
|
1428
1433
|
public async validateRestore(cfg): Promise<InterfaceServerResponse> {
|
|
1429
1434
|
try {
|
|
1430
1435
|
let response = await this.sendClientRequest('PUT', '/config/restore/validate', cfg, 10000);
|
|
1431
1436
|
return response;
|
|
1432
|
-
} catch (err) {
|
|
1437
|
+
} catch (err) {
|
|
1438
|
+
logger.error(`Error requesting PUT /config/restore/validate ${err.message}`);
|
|
1439
|
+
let errorResponse = new InterfaceServerResponse();
|
|
1440
|
+
errorResponse.error = new Error(`Error requesting PUT /config/restore/validate: ${err.message}`);
|
|
1441
|
+
return errorResponse;
|
|
1442
|
+
}
|
|
1433
1443
|
}
|
|
1434
1444
|
public async restoreConfig(cfg): Promise<InterfaceServerResponse> {
|
|
1435
1445
|
try {
|
|
1436
1446
|
return await this.sendClientRequest('PUT', '/config/restore/file', cfg, 20000);
|
|
1437
|
-
} catch (err) {
|
|
1447
|
+
} catch (err) {
|
|
1448
|
+
logger.error(`Error requesting PUT /config/restore/file ${err.message}`);
|
|
1449
|
+
let errorResponse = new InterfaceServerResponse();
|
|
1450
|
+
errorResponse.error = new Error(`Error requesting PUT /config/restore/file: ${err.message}`);
|
|
1451
|
+
return errorResponse;
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
public async startPacketCapture(): Promise<InterfaceServerResponse> {
|
|
1455
|
+
try {
|
|
1456
|
+
let response = await this.sendClientRequest('PUT', '/config/packetCapture/start', undefined, 10000);
|
|
1457
|
+
return response;
|
|
1458
|
+
} catch (err) {
|
|
1459
|
+
logger.error(`Error requesting PUT /config/packetCapture/start: ${err.message}`);
|
|
1460
|
+
let errorResponse = new InterfaceServerResponse();
|
|
1461
|
+
errorResponse.error = new Error(`Error requesting PUT /config/packetCapture/start: ${err.message}`);
|
|
1462
|
+
return errorResponse;
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
public async stopPacketCapture(): Promise<InterfaceServerResponse> {
|
|
1466
|
+
try {
|
|
1467
|
+
let response = await this.sendClientRequest('PUT', '/config/packetCapture/stop', undefined, 10000);
|
|
1468
|
+
return response;
|
|
1469
|
+
} catch (err) {
|
|
1470
|
+
logger.error(`Error requesting PUT /config/packetCapture/stop: ${err.message}`);
|
|
1471
|
+
let errorResponse = new InterfaceServerResponse();
|
|
1472
|
+
errorResponse.error = new Error(`Error requesting PUT /config/packetCapture/stop: ${err.message}`);
|
|
1473
|
+
return errorResponse;
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
public async getPacketCaptureLog(): Promise<InterfaceServerResponse> {
|
|
1477
|
+
try {
|
|
1478
|
+
let response = await this.sendClientRequest('GET', '/config/packetCapture/log', undefined, 15000);
|
|
1479
|
+
return response;
|
|
1480
|
+
} catch (err) {
|
|
1481
|
+
logger.error(`Error requesting GET /config/packetCapture/log: ${err.message}`);
|
|
1482
|
+
let errorResponse = new InterfaceServerResponse();
|
|
1483
|
+
errorResponse.error = new Error(`Error requesting GET /config/packetCapture/log: ${err.message}`);
|
|
1484
|
+
return errorResponse;
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
|
|
1489
|
+
// Static methods to handle the REM server
|
|
1490
|
+
public static async startPacketCaptureOnRemServer(): Promise<void> {
|
|
1491
|
+
let remServers = webApp.findServersByType('rem') as REMInterfaceServer[];
|
|
1492
|
+
logger.info(`Found ${remServers ? remServers.length : 0} REM servers`);
|
|
1493
|
+
|
|
1494
|
+
if (remServers && remServers.length > 0) {
|
|
1495
|
+
let server = remServers[0]; // Get the single REM server
|
|
1496
|
+
logger.info(`Attempting to start packet capture on REM server: ${server.name} (connected: ${server.isConnected})`);
|
|
1497
|
+
|
|
1498
|
+
if (server.isConnected) {
|
|
1499
|
+
try {
|
|
1500
|
+
let response = await server.startPacketCapture();
|
|
1501
|
+
logger.info(`Start packet capture response: ${JSON.stringify(response)}`);
|
|
1502
|
+
|
|
1503
|
+
if (response && response.status.code === 200) {
|
|
1504
|
+
logger.info(`Started packet capture on REM server: ${server.name}`);
|
|
1505
|
+
} else {
|
|
1506
|
+
logger.warn(`Failed to start packet capture on REM server: ${server.name}. Status: ${response?.status?.code}, Error: ${response?.error?.message}`);
|
|
1507
|
+
}
|
|
1508
|
+
} catch (err) {
|
|
1509
|
+
logger.error(`Error starting packet capture on REM server ${server.name}: ${err.message}`);
|
|
1510
|
+
}
|
|
1511
|
+
} else {
|
|
1512
|
+
logger.warn(`REM server ${server.name} is not connected, cannot start packet capture`);
|
|
1513
|
+
}
|
|
1514
|
+
} else {
|
|
1515
|
+
logger.warn(`No REM servers found or configured`);
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
public static async stopPacketCaptureOnRemServer(): Promise<any[]> {
|
|
1520
|
+
let remServers = webApp.findServersByType('rem') as REMInterfaceServer[];
|
|
1521
|
+
let remLogs = [];
|
|
1522
|
+
|
|
1523
|
+
logger.info(`Found ${remServers ? remServers.length : 0} REM servers for stop packet capture`);
|
|
1524
|
+
|
|
1525
|
+
if (remServers && remServers.length > 0) {
|
|
1526
|
+
let server = remServers[0]; // Get the single REM server
|
|
1527
|
+
logger.info(`Attempting to stop packet capture on REM server: ${server.name} (connected: ${server.isConnected})`);
|
|
1528
|
+
|
|
1529
|
+
if (server.isConnected) {
|
|
1530
|
+
try {
|
|
1531
|
+
// Stop packet capture
|
|
1532
|
+
let stopResponse = await server.stopPacketCapture();
|
|
1533
|
+
logger.info(`Stop packet capture response: ${JSON.stringify(stopResponse)}`);
|
|
1534
|
+
|
|
1535
|
+
if (stopResponse && stopResponse.status.code === 200) {
|
|
1536
|
+
logger.info(`Stopped packet capture on REM server: ${server.name}`);
|
|
1537
|
+
|
|
1538
|
+
// Get the log file
|
|
1539
|
+
let logResponse = await server.getPacketCaptureLog();
|
|
1540
|
+
logger.info(`Get log response: ${JSON.stringify(logResponse)}`);
|
|
1541
|
+
|
|
1542
|
+
if (logResponse && logResponse.status.code === 200 && logResponse.data) {
|
|
1543
|
+
// Use the actual log file name from the REM response
|
|
1544
|
+
logger.info(`Log response obj: ${JSON.stringify(logResponse.obj)}`);
|
|
1545
|
+
let logFileName = logResponse.obj && logResponse.obj.logFile ? logResponse.obj.logFile : `rem_${server.name}_packetCapture.log`;
|
|
1546
|
+
logger.info(`Using log filename: ${logFileName}`);
|
|
1547
|
+
remLogs.push({
|
|
1548
|
+
serverName: server.name,
|
|
1549
|
+
logData: logResponse.data,
|
|
1550
|
+
logFileName: logFileName
|
|
1551
|
+
});
|
|
1552
|
+
logger.info(`Retrieved packet capture log from REM server: ${server.name}, log size: ${logResponse.data.length} characters, filename: ${logFileName}`);
|
|
1553
|
+
} else {
|
|
1554
|
+
logger.warn(`Failed to retrieve packet capture log from REM server: ${server.name}. Status: ${logResponse?.status?.code}, Error: ${logResponse?.error?.message}`);
|
|
1555
|
+
}
|
|
1556
|
+
} else {
|
|
1557
|
+
logger.warn(`Failed to stop packet capture on REM server: ${server.name}. Status: ${stopResponse?.status?.code}, Error: ${stopResponse?.error?.message}`);
|
|
1558
|
+
}
|
|
1559
|
+
} catch (err) {
|
|
1560
|
+
logger.error(`Error stopping packet capture on REM server ${server.name}: ${err.message}`);
|
|
1561
|
+
}
|
|
1562
|
+
} else {
|
|
1563
|
+
logger.warn(`REM server ${server.name} is not connected, cannot stop packet capture`);
|
|
1564
|
+
}
|
|
1565
|
+
} else {
|
|
1566
|
+
logger.warn(`No REM servers found or configured for stop packet capture`);
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
logger.info(`Returning ${remLogs.length} REM logs`);
|
|
1570
|
+
return remLogs;
|
|
1438
1571
|
}
|
|
1439
1572
|
private async initConnection() {
|
|
1440
1573
|
try {
|
|
@@ -1483,12 +1616,15 @@ export class REMInterfaceServer extends ProtoServer {
|
|
|
1483
1616
|
resolve();
|
|
1484
1617
|
}
|
|
1485
1618
|
}
|
|
1486
|
-
catch (err) {
|
|
1619
|
+
catch (err) {
|
|
1620
|
+
logger.error(`initConnection setTimeout error: ${err.message}`);
|
|
1621
|
+
reject(new Error(`initConnection setTimeout: ${err.message}`));
|
|
1622
|
+
}
|
|
1487
1623
|
}, 3000);
|
|
1488
1624
|
});
|
|
1489
1625
|
}
|
|
1490
1626
|
catch (err) {
|
|
1491
|
-
logger.error(`Error with REM Interface Server initConnection: ${err}`)
|
|
1627
|
+
logger.error(`Error with REM Interface Server initConnection: ${err.message}`);
|
|
1492
1628
|
}
|
|
1493
1629
|
}
|
|
1494
1630
|
public async stopAsync() {
|
|
@@ -1556,7 +1692,10 @@ export class REMInterfaceServer extends ProtoServer {
|
|
|
1556
1692
|
});
|
|
1557
1693
|
req.on('abort', () => { logger.warn('Request Aborted'); reject(new Error('Request Aborted.')); });
|
|
1558
1694
|
req.end(sbody);
|
|
1559
|
-
}).catch((err) => {
|
|
1695
|
+
}).catch((err) => {
|
|
1696
|
+
logger.error(`Error Sending REM Request: ${opts.method} ${url} ${err.message}`);
|
|
1697
|
+
ret.error = err;
|
|
1698
|
+
});
|
|
1560
1699
|
logger.verbose(`REM server request returned. ${opts.method} ${opts.path} ${sbody}`);
|
|
1561
1700
|
if (ret.status.code > 200) {
|
|
1562
1701
|
// We have an http error so let's parse it up.
|
|
@@ -1574,7 +1713,9 @@ export class REMInterfaceServer extends ProtoServer {
|
|
|
1574
1713
|
}
|
|
1575
1714
|
catch (err) {
|
|
1576
1715
|
logger.error(`Error sending HTTP ${method} command to ${url}: ${err.message}`);
|
|
1577
|
-
|
|
1716
|
+
let errorResponse = new InterfaceServerResponse();
|
|
1717
|
+
errorResponse.error = new Error(`Http ${method} Error ${url}:${err.message}`);
|
|
1718
|
+
return errorResponse;
|
|
1578
1719
|
}
|
|
1579
1720
|
}
|
|
1580
1721
|
private initSockets() {
|
|
@@ -1585,7 +1726,10 @@ export class REMInterfaceServer extends ProtoServer {
|
|
|
1585
1726
|
//console.log(this.cfg);
|
|
1586
1727
|
this.sockClient = sockClient(url, extend(true,
|
|
1587
1728
|
{ reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000, transports: ['websocket'], upgrade: true, }, this.cfg.socket));
|
|
1588
|
-
if (typeof this.sockClient === 'undefined')
|
|
1729
|
+
if (typeof this.sockClient === 'undefined') {
|
|
1730
|
+
logger.error('Could not Initialize REM Server. Invalid configuration.');
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1589
1733
|
//this.sockClient = io.connect(url, { reconnectionDelay: 2000, reconnection: true, reconnectionDelayMax: 20000 });
|
|
1590
1734
|
//console.log(this.sockClient);
|
|
1591
1735
|
//console.log(typeof this.sockClient.on);
|
|
@@ -1604,7 +1748,9 @@ export class REMInterfaceServer extends ProtoServer {
|
|
|
1604
1748
|
});
|
|
1605
1749
|
this.isRunning = true;
|
|
1606
1750
|
}
|
|
1607
|
-
catch (err) {
|
|
1751
|
+
catch (err) {
|
|
1752
|
+
logger.error(`Error Initializing Sockets: ${err.message}`);
|
|
1753
|
+
}
|
|
1608
1754
|
}
|
|
1609
1755
|
private isJSONString(s: string): boolean {
|
|
1610
1756
|
if (typeof s !== 'string') return false;
|
|
@@ -1613,23 +1759,23 @@ export class REMInterfaceServer extends ProtoServer {
|
|
|
1613
1759
|
}
|
|
1614
1760
|
public async getApiService(url: string, data?: any, timeout: number = 3600): Promise<InterfaceServerResponse> {
|
|
1615
1761
|
// Calls a rest service on the REM to set the state of a connected device.
|
|
1616
|
-
|
|
1617
|
-
|
|
1762
|
+
let ret = await this.sendClientRequest('GET', url, data, timeout);
|
|
1763
|
+
return ret;
|
|
1618
1764
|
}
|
|
1619
1765
|
public async putApiService(url: string, data?: any, timeout: number = 3600): Promise<InterfaceServerResponse> {
|
|
1620
1766
|
// Calls a rest service on the REM to set the state of a connected device.
|
|
1621
|
-
|
|
1622
|
-
|
|
1767
|
+
let ret = await this.sendClientRequest('PUT', url, data, timeout);
|
|
1768
|
+
return ret;
|
|
1623
1769
|
}
|
|
1624
1770
|
public async searchApiService(url: string, data?: any, timeout: number = 3600): Promise<InterfaceServerResponse> {
|
|
1625
1771
|
// Calls a rest service on the REM to set the state of a connected device.
|
|
1626
|
-
|
|
1627
|
-
|
|
1772
|
+
let ret = await this.sendClientRequest('SEARCH', url, data, timeout);
|
|
1773
|
+
return ret;
|
|
1628
1774
|
}
|
|
1629
1775
|
public async deleteApiService(url: string, data?: any, timeout: number = 3600): Promise<InterfaceServerResponse> {
|
|
1630
1776
|
// Calls a rest service on the REM to set the state of a connected device.
|
|
1631
|
-
|
|
1632
|
-
|
|
1777
|
+
let ret = await this.sendClientRequest('DELETE', url, data, timeout);
|
|
1778
|
+
return ret;
|
|
1633
1779
|
}
|
|
1634
1780
|
public async getDevices() {
|
|
1635
1781
|
try {
|
|
@@ -1640,7 +1786,10 @@ export class REMInterfaceServer extends ProtoServer {
|
|
|
1640
1786
|
}
|
|
1641
1787
|
return (response.status.code === 200) ? JSON.parse(response.data) : [];
|
|
1642
1788
|
}
|
|
1643
|
-
catch (err) {
|
|
1789
|
+
catch (err) {
|
|
1790
|
+
logger.error(`getDevices: ${err.message}`);
|
|
1791
|
+
return [];
|
|
1792
|
+
}
|
|
1644
1793
|
}
|
|
1645
1794
|
}
|
|
1646
1795
|
export class BackupFile {
|
|
@@ -74,7 +74,7 @@ export class ConfigRoute {
|
|
|
74
74
|
let cport = extend(true, { enabled: false, netConnect: false, mock: false }, cfg[section]);
|
|
75
75
|
let port = conn.findPortById(cport.portId || 0);
|
|
76
76
|
if (typeof cport.type === 'undefined'){
|
|
77
|
-
cport.type = cport.netConnect ? 'netConnect' : cport.
|
|
77
|
+
cport.type = cport.netConnect ? 'netConnect' : cport.mock ? 'mock' : 'local'
|
|
78
78
|
}
|
|
79
79
|
if (typeof port !== 'undefined') cport.stats = port.stats;
|
|
80
80
|
if (port.portId === 0 && port.type === 'screenlogic') {
|
|
@@ -301,7 +301,8 @@ export class ConfigRoute {
|
|
|
301
301
|
// waterFlow: sys.board.valueMaps.chemControllerWaterFlow.toArray(), // remove
|
|
302
302
|
controllers: sys.chemControllers.get(),
|
|
303
303
|
maxChemControllers: sys.equipment.maxChemControllers,
|
|
304
|
-
doserTypes: sys.board.valueMaps.chemDoserTypes.toArray()
|
|
304
|
+
doserTypes: sys.board.valueMaps.chemDoserTypes.toArray(),
|
|
305
|
+
chlorinators: sys.chlorinators.get(),
|
|
305
306
|
};
|
|
306
307
|
return res.status(200).send(opts);
|
|
307
308
|
}
|
|
@@ -1008,7 +1009,7 @@ export class ConfigRoute {
|
|
|
1008
1009
|
return next(new ServiceProcessError(`File already exists ${req.file.originalname}`, 'POST: app/backup/file', 'writeFile'));
|
|
1009
1010
|
else {
|
|
1010
1011
|
try {
|
|
1011
|
-
fs.writeFileSync(bf.filePath, req.file.buffer);
|
|
1012
|
+
fs.writeFileSync(bf.filePath, new Uint8Array(req.file.buffer));
|
|
1012
1013
|
} catch (e) { logger.error(`Error writing backup file ${e.message}`); }
|
|
1013
1014
|
}
|
|
1014
1015
|
return res.status(200).send(bf);
|