nodejs-poolcontroller 8.0.2 → 8.0.5
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/.github/workflows/docker-publish-njsPC-linux.yml +28 -59
- package/Dockerfile +3 -2
- package/controller/State.ts +4 -1
- package/controller/boards/IntelliCenterBoard.ts +17 -5
- package/controller/boards/SystemBoard.ts +5 -2
- package/controller/comms/Comms.ts +3 -0
- package/controller/comms/ScreenLogic.ts +83 -84
- package/controller/comms/messages/status/PumpStateMessage.ts +1 -1
- package/controller/nixie/circuits/Circuit.ts +13 -8
- package/controller/nixie/pumps/Pump.ts +6 -2
- package/package.json +1 -1
- package/.docker/Dockerfile.armv6 +0 -29
- package/.docker/Dockerfile.armv7 +0 -29
- package/.docker/Dockerfile.linux +0 -62
- package/.docker/Dockerfile.windows +0 -43
- package/.docker/docker-compose.yml +0 -47
- package/.docker/ecosystem.config.js +0 -35
- package/.github/workflows/docker-publish-njsPC-windows.yml +0 -41
|
@@ -4,30 +4,37 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
6
|
- master
|
|
7
|
-
|
|
7
|
+
tags:
|
|
8
|
+
- "v*.*.*"
|
|
8
9
|
workflow_dispatch:
|
|
9
10
|
|
|
10
11
|
jobs:
|
|
11
12
|
build-and-push:
|
|
12
13
|
runs-on: ubuntu-latest
|
|
13
14
|
steps:
|
|
14
|
-
- name:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- name: Checkout code from tagyoureit/nodejs-poolcontroller
|
|
18
|
-
uses: actions/checkout@v3
|
|
19
|
-
with:
|
|
20
|
-
repository: tagyoureit/nodejs-poolcontroller
|
|
21
|
-
ref: master # or specify the branch or tag to pull from
|
|
22
|
-
path: nodejs-poolcontroller
|
|
23
|
-
|
|
24
|
-
- name: Checkout code from rstrouse/nodejs-poolcontroller-dashpanel
|
|
25
|
-
uses: actions/checkout@v3
|
|
15
|
+
- name: Docker meta
|
|
16
|
+
id: meta
|
|
17
|
+
uses: docker/metadata-action@v5
|
|
26
18
|
with:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
# list of Docker images to use as base name for tags
|
|
20
|
+
images: |
|
|
21
|
+
tagyoureit/njspc
|
|
22
|
+
# generate Docker tags based on the following events/attributes
|
|
23
|
+
tags: |
|
|
24
|
+
type=schedule
|
|
25
|
+
type=ref,event=branch
|
|
26
|
+
type=ref,event=pr
|
|
27
|
+
type=semver,pattern={{version}}
|
|
28
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
29
|
+
type=semver,pattern={{major}}
|
|
30
|
+
type=sha
|
|
31
|
+
|
|
32
|
+
- name: Set up QEMU
|
|
33
|
+
uses: docker/setup-qemu-action@v3
|
|
34
|
+
|
|
35
|
+
- name: Set up Docker Buildx
|
|
36
|
+
uses: docker/setup-buildx-action@v3
|
|
37
|
+
|
|
31
38
|
- name: Login to Docker Hub
|
|
32
39
|
uses: docker/login-action@v3
|
|
33
40
|
with:
|
|
@@ -35,47 +42,9 @@ jobs:
|
|
|
35
42
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
36
43
|
|
|
37
44
|
- name: Build and push combined Docker image
|
|
38
|
-
uses: docker/build-push-action@
|
|
45
|
+
uses: docker/build-push-action@v6
|
|
39
46
|
with:
|
|
40
|
-
context: .
|
|
41
|
-
file: ./.docker/Dockerfile.linux
|
|
42
47
|
push: true
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
# - name: Build and push njsPC Linux Docker image (x86_64)
|
|
48
|
-
# uses: docker/build-push-action@v4
|
|
49
|
-
# with:
|
|
50
|
-
# context: .
|
|
51
|
-
# file: ./.docker/Dockerfile.linux
|
|
52
|
-
# push: true
|
|
53
|
-
# tags: |
|
|
54
|
-
# tagyoureit/nodejs-poolcontroller:latest
|
|
55
|
-
|
|
56
|
-
# - name: Build and push njsPC-dP Linux Docker image (x86_64)
|
|
57
|
-
# uses: docker/build-push-action@v4
|
|
58
|
-
# with:
|
|
59
|
-
# context: nodejs-poolcontroller-dashpanel
|
|
60
|
-
# file: ./.docker/Dockerfile.linux
|
|
61
|
-
# push: true
|
|
62
|
-
# tags: |
|
|
63
|
-
# rstrouse/nodejs-poolcontroller-dashpanel:latest
|
|
64
|
-
|
|
65
|
-
# - name: Build and push ARMv7 Docker image
|
|
66
|
-
# uses: docker/build-push-action@v4
|
|
67
|
-
# with:
|
|
68
|
-
# context: .
|
|
69
|
-
# file: ./.docker/Dockerfile.armv7 # Adjust the path to your ARMv7 Dockerfile
|
|
70
|
-
# push: true
|
|
71
|
-
# tags: |
|
|
72
|
-
# tagyoureit/nodejs-poolcontroller-armv7:latest
|
|
73
|
-
|
|
74
|
-
# - name: Build and push ARMv6 Docker image
|
|
75
|
-
# uses: docker/build-push-action@v4
|
|
76
|
-
# with:
|
|
77
|
-
# context: .
|
|
78
|
-
# file: ./.docker/Dockerfile.armv6 # Adjust the path to your ARMv6 Dockerfile
|
|
79
|
-
# push: true
|
|
80
|
-
# tags: |
|
|
81
|
-
# tagyoureit/nodejs-poolcontroller-armv6:latest
|
|
48
|
+
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
|
49
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
50
|
+
labels: ${{ steps.meta.outputs.labels }}
|
package/Dockerfile
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
FROM node:
|
|
1
|
+
FROM node:18-alpine AS build
|
|
2
2
|
RUN apk add --no-cache make gcc g++ python3 linux-headers udev tzdata
|
|
3
3
|
WORKDIR /app
|
|
4
4
|
COPY package*.json ./
|
|
@@ -8,11 +8,12 @@ COPY . .
|
|
|
8
8
|
RUN npm run build
|
|
9
9
|
RUN npm ci --omit=dev
|
|
10
10
|
|
|
11
|
-
FROM node:
|
|
11
|
+
FROM node:18-alpine as prod
|
|
12
12
|
RUN apk add git
|
|
13
13
|
RUN mkdir /app && chown node:node /app
|
|
14
14
|
WORKDIR /app
|
|
15
15
|
COPY --chown=node:node --from=build /app .
|
|
16
16
|
USER node
|
|
17
17
|
ENV NODE_ENV=production
|
|
18
|
+
EXPOSE 5150
|
|
18
19
|
ENTRYPOINT ["node", "dist/app.js"]
|
package/controller/State.ts
CHANGED
|
@@ -1089,7 +1089,9 @@ export class ScheduleStateCollection extends EqStateCollection<ScheduleState> {
|
|
|
1089
1089
|
let ssched = this.getItemByIndex(i);
|
|
1090
1090
|
let st = ssched.scheduleTime;
|
|
1091
1091
|
let sched = sys.schedules.getItemById(ssched.id);
|
|
1092
|
-
|
|
1092
|
+
// rsg st.startTime is null when the schedule has No Days <-- WRONG. ssched.scheduleDays should be checked.
|
|
1093
|
+
// original fix #879; updated fix #1033
|
|
1094
|
+
if (!sched.isActive || ssched.disabled || ssched.scheduleDays === 0) {
|
|
1093
1095
|
continue;
|
|
1094
1096
|
}
|
|
1095
1097
|
st.calcSchedule(state.time, sys.schedules.getItemById(ssched.id));
|
|
@@ -1837,6 +1839,7 @@ export class HeaterState extends EqState {
|
|
|
1837
1839
|
public set prevHeaterOffTemp(val: number) {
|
|
1838
1840
|
if (this.prevHeaterOffTemp !== val) {
|
|
1839
1841
|
this.data.prevHeaterOffTemp = val;
|
|
1842
|
+
if (typeof val === 'undefined') delete this.data.prevHeaterOffTemp;
|
|
1840
1843
|
}
|
|
1841
1844
|
}
|
|
1842
1845
|
public get startupDelay(): boolean { return this.data.startupDelay; }
|
|
@@ -2173,6 +2173,7 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2173
2173
|
255, 255, 0, 0, 0, 0], // 30-35
|
|
2174
2174
|
3);
|
|
2175
2175
|
|
|
2176
|
+
|
|
2176
2177
|
// Circuits are always contiguous so we don't have to worry about
|
|
2177
2178
|
// them having a strange offset like features and groups. However, in
|
|
2178
2179
|
// single body systems they start with 2.
|
|
@@ -2180,13 +2181,14 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2180
2181
|
// We are using the index and setting the circuits based upon
|
|
2181
2182
|
// the index. This way it doesn't matter what the sort happens to
|
|
2182
2183
|
// be and whether there are gaps in the ids or not. The ordinal is the bit number.
|
|
2183
|
-
let
|
|
2184
|
-
let ordinal =
|
|
2184
|
+
let cstate = state.circuits.getItemByIndex(i);
|
|
2185
|
+
let ordinal = cstate.id - 1;
|
|
2186
|
+
if (ordinal >= 40) continue;
|
|
2185
2187
|
let ndx = Math.floor(ordinal / 8);
|
|
2186
2188
|
let byte = out.payload[ndx + 3];
|
|
2187
2189
|
let bit = ordinal - (ndx * 8);
|
|
2188
|
-
if (
|
|
2189
|
-
else if (
|
|
2190
|
+
if (cstate.id === id) byte = isOn ? byte = byte | (1 << bit) : byte;
|
|
2191
|
+
else if (cstate.isOn) byte = byte | (1 << bit);
|
|
2190
2192
|
out.payload[ndx + 3] = byte;
|
|
2191
2193
|
}
|
|
2192
2194
|
// Set the bits for the features.
|
|
@@ -2196,6 +2198,7 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2196
2198
|
// be and whether there are gaps in the ids or not. The ordinal is the bit number.
|
|
2197
2199
|
let feature = state.features.getItemByIndex(i);
|
|
2198
2200
|
let ordinal = feature.id - sys.board.equipmentIds.features.start;
|
|
2201
|
+
if (ordinal >= 32) continue;
|
|
2199
2202
|
let ndx = Math.floor(ordinal / 8);
|
|
2200
2203
|
let byte = out.payload[ndx + 9];
|
|
2201
2204
|
let bit = ordinal - (ndx * 8);
|
|
@@ -2207,6 +2210,7 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2207
2210
|
for (let i = 0; i < state.data.circuitGroups.length; i++) {
|
|
2208
2211
|
let group = state.circuitGroups.getItemByIndex(i);
|
|
2209
2212
|
let ordinal = group.id - sys.board.equipmentIds.circuitGroups.start;
|
|
2213
|
+
if (ordinal >= 16) continue;
|
|
2210
2214
|
let ndx = Math.floor(ordinal / 8);
|
|
2211
2215
|
let byte = out.payload[ndx + 13];
|
|
2212
2216
|
let bit = ordinal - (ndx * 8);
|
|
@@ -2218,6 +2222,7 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2218
2222
|
for (let i = 0; i < state.data.lightGroups.length; i++) {
|
|
2219
2223
|
let group = state.lightGroups.getItemByIndex(i);
|
|
2220
2224
|
let ordinal = group.id - sys.board.equipmentIds.circuitGroups.start;
|
|
2225
|
+
if (ordinal >= 16) continue;
|
|
2221
2226
|
let ndx = Math.floor(ordinal / 8);
|
|
2222
2227
|
let byte = out.payload[ndx + 13];
|
|
2223
2228
|
let bit = ordinal - (ndx * 8);
|
|
@@ -2253,6 +2258,7 @@ class IntelliCenterCircuitCommands extends CircuitCommands {
|
|
|
2253
2258
|
for (let i = 0; i < state.data.schedules.length; i++) {
|
|
2254
2259
|
let sched = state.schedules.getItemByIndex(i);
|
|
2255
2260
|
let ordinal = sched.id - 1;
|
|
2261
|
+
if (ordinal >= 100) continue;
|
|
2256
2262
|
let ndx = Math.floor(ordinal / 8);
|
|
2257
2263
|
let byte = out.payload[ndx + 15];
|
|
2258
2264
|
let bit = ordinal - (ndx * 8);
|
|
@@ -2822,6 +2828,7 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
2822
2828
|
body2: { heatMode: number, heatSetpoint: number, coolSetpoint: number }
|
|
2823
2829
|
};
|
|
2824
2830
|
private async queueBodyHeatSettings(bodyId?: number, byte?: number, data?: any): Promise<Boolean> {
|
|
2831
|
+
logger.debug(`queueBodyHeatSettings: ${JSON.stringify(this.bodyHeatSettings)}`); // remove this line if #848 is fixed
|
|
2825
2832
|
if (typeof this.bodyHeatSettings === 'undefined') {
|
|
2826
2833
|
let body1 = sys.bodies.getItemById(1);
|
|
2827
2834
|
let body2 = sys.bodies.getItemById(2);
|
|
@@ -2884,10 +2891,12 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
2884
2891
|
state.emitEquipmentChanges();
|
|
2885
2892
|
} catch (err) {
|
|
2886
2893
|
bhs.processing = false;
|
|
2894
|
+
bhs.bytes = [];
|
|
2887
2895
|
throw (err);
|
|
2888
2896
|
}
|
|
2889
2897
|
finally {
|
|
2890
2898
|
bhs.processing = false;
|
|
2899
|
+
bhs.bytes = [];
|
|
2891
2900
|
}
|
|
2892
2901
|
return true;
|
|
2893
2902
|
}
|
|
@@ -2897,7 +2906,10 @@ class IntelliCenterBodyCommands extends BodyCommands {
|
|
|
2897
2906
|
setTimeout(async () => {
|
|
2898
2907
|
try {
|
|
2899
2908
|
await this.queueBodyHeatSettings();
|
|
2900
|
-
} catch (err) {
|
|
2909
|
+
} catch (err) {
|
|
2910
|
+
logger.error(`Error sending queued body setpoint message: ${err.message}`);
|
|
2911
|
+
throw (err);
|
|
2912
|
+
}
|
|
2901
2913
|
}, 3000);
|
|
2902
2914
|
}
|
|
2903
2915
|
else bhs.processing = false;
|
|
@@ -1762,6 +1762,7 @@ export class BodyCommands extends BoardCommands {
|
|
|
1762
1762
|
let bdy = sys.bodies.getItemById(body.id);
|
|
1763
1763
|
let bstate = state.temps.bodies.getItemById(body.id);
|
|
1764
1764
|
bdy.heatMode = bstate.heatMode = mode;
|
|
1765
|
+
sys.board.heaters.clearPrevHeaterOffTemp();
|
|
1765
1766
|
sys.board.heaters.syncHeaterStates();
|
|
1766
1767
|
state.emitEquipmentChanges();
|
|
1767
1768
|
return Promise.resolve(bstate);
|
|
@@ -1770,6 +1771,7 @@ export class BodyCommands extends BoardCommands {
|
|
|
1770
1771
|
let bdy = sys.bodies.getItemById(body.id);
|
|
1771
1772
|
let bstate = state.temps.bodies.getItemById(body.id);
|
|
1772
1773
|
bdy.setPoint = bstate.setPoint = setPoint;
|
|
1774
|
+
sys.board.heaters.clearPrevHeaterOffTemp();
|
|
1773
1775
|
state.emitEquipmentChanges();
|
|
1774
1776
|
sys.board.heaters.syncHeaterStates();
|
|
1775
1777
|
return Promise.resolve(bstate);
|
|
@@ -3629,7 +3631,7 @@ export class ScheduleCommands extends BoardCommands {
|
|
|
3629
3631
|
if (heatSetpoint < 0 || heatSetpoint > 104) return Promise.reject(new InvalidEquipmentDataError(`Invalid heat setpoint: ${heatSetpoint}`, 'Schedule', heatSetpoint));
|
|
3630
3632
|
if (sys.board.circuits.getCircuitReferences(true, true, false, true).find(elem => elem.id === circuit) === undefined)
|
|
3631
3633
|
return Promise.reject(new InvalidEquipmentDataError(`Invalid circuit reference: ${circuit}`, 'Schedule', circuit));
|
|
3632
|
-
if (schedType === 128 && schedDays === 0) return Promise.reject(new InvalidEquipmentDataError(`Invalid schedule days: ${schedDays}. You must supply days that the schedule is to run.`, 'Schedule', schedDays));
|
|
3634
|
+
if (schedType === 128 && schedDays === 0) return Promise.reject(new InvalidEquipmentDataError(`Invalid schedule days: ${schedDays}. You must supply days that the schedule is to run.`, 'Schedule', schedDays)); // rsg 2024.11.22 - some controllers allow no days.
|
|
3633
3635
|
|
|
3634
3636
|
// If we made it to here we are valid and the schedula and it state should exist.
|
|
3635
3637
|
sched = sys.schedules.getItemById(id, true);
|
|
@@ -4610,7 +4612,8 @@ export class ValveCommands extends BoardCommands {
|
|
|
4610
4612
|
let drain = sys.equipment.shared ? typeof state.circuits.get().find(elem => typeof elem.type !== 'undefined' && elem.type.name === 'spadrain' && elem.isOn === true) !== 'undefined' ||
|
|
4611
4613
|
typeof state.features.get().find(elem => typeof elem.type !== 'undefined' && elem.type.name === 'spadrain' && elem.isOn === true) !== 'undefined' : false;
|
|
4612
4614
|
// Check to see if there is a spillway circuit or feature on. If it is on then the return will be diverted no mater what.
|
|
4613
|
-
let spillway = sys.equipment.shared ?
|
|
4615
|
+
let spillway = sys.equipment.shared ?
|
|
4616
|
+
typeof state.circuits.get().find(elem => typeof elem.type !== 'undefined' && elem.type.name === 'spillway' && elem.isOn === true) !== 'undefined' ||
|
|
4614
4617
|
typeof state.features.get().find(elem => typeof elem.type !== 'undefined' && elem.type.name === 'spillway' && elem.isOn === true) !== 'undefined' : false;
|
|
4615
4618
|
let spa = sys.equipment.shared ? state.circuits.getItemById(1).isOn : false;
|
|
4616
4619
|
let pool = sys.equipment.shared ? state.circuits.getItemById(6).isOn : false;
|
|
@@ -668,6 +668,9 @@ export class RS485Port {
|
|
|
668
668
|
let opts: SerialPortOpenOptions<AutoDetectTypes> = { path: portPath, autoOpen: false, baudRate: 9600 };
|
|
669
669
|
sp = new SerialPortMock(opts);
|
|
670
670
|
}
|
|
671
|
+
else if (this._cfg.type === 'screenlogic') {
|
|
672
|
+
return await sl.openAsync();
|
|
673
|
+
}
|
|
671
674
|
else {
|
|
672
675
|
this.mock = false;
|
|
673
676
|
let opts: SerialPortOpenOptions<AutoDetectTypes> = extend(true, { path: this._cfg.rs485Port }, this._cfg.portSettings);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ControllerType, Timestamp, Utils, utils } from '../../controller/Constants';
|
|
2
|
-
import { LightGroup, LightGroupCircuit, sys, Valve, Body, Pump, PumpCircuit, Remote} from '../../controller/Equipment';
|
|
2
|
+
import { LightGroup, LightGroupCircuit, sys, Valve, Body, Pump, PumpCircuit, Remote } from '../../controller/Equipment';
|
|
3
3
|
import { CircuitState, state, ValveState } from '../../controller/State';
|
|
4
4
|
import { RemoteLogin, UnitConnection, FindUnits, SLEquipmentStateData, SLIntellichlorData, SLPumpStatusData, SLScheduleData, SLSystemTimeData, HeatModes, SLControllerConfigData, SLEquipmentConfigurationData, HeaterConfig, Valves, SLChemData, SLGetCustomNamesData } from 'node-screenlogic';
|
|
5
5
|
import * as Screenlogic from 'node-screenlogic';
|
|
@@ -87,7 +87,7 @@ export class ScreenLogicComms {
|
|
|
87
87
|
logger.screenlogic(msg);
|
|
88
88
|
})
|
|
89
89
|
let ver = await this._client.getVersionAsync();
|
|
90
|
-
logger.info(`Screenlogic: connect to ${systemName} ${ver} at ${unit.ipAddr}:${unit.port}`);
|
|
90
|
+
logger.info(`Screenlogic: connect to ${systemName} ${ver.version} at ${unit.ipAddr}:${unit.port}`);
|
|
91
91
|
|
|
92
92
|
let addClient = await this._client.addClientAsync();
|
|
93
93
|
logger.silly(`Screenlogic:Add client result: ${addClient}`);
|
|
@@ -912,21 +912,21 @@ class Controller {
|
|
|
912
912
|
}
|
|
913
913
|
], */
|
|
914
914
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
915
|
+
public static decodeHighSpeed(highSpeed: number[]) {
|
|
916
|
+
let maxCircuits = sys.controllerType === ControllerType.IntelliTouch ? 8 : 4;
|
|
917
|
+
let arrCircuits = [];
|
|
918
|
+
let pump = sys.pumps.find(x => { return x.master !== 1 && x.type === 65 });
|
|
919
|
+
for (let i = 0; i < maxCircuits && i < highSpeed.length; i++) {
|
|
920
|
+
let val = highSpeed[i];
|
|
921
|
+
if (val > 0) arrCircuits.push(val);
|
|
922
|
+
else if (typeof pump !== 'undefined') pump.circuits.removeItemById(i);
|
|
923
|
+
}
|
|
924
|
+
if (arrCircuits.length > 0) {
|
|
925
|
+
let pump = sys.pumps.getDualSpeed(true);
|
|
926
|
+
for (let j = 1; j <= arrCircuits.length; j++) pump.circuits.getItemById(j, true).circuit = arrCircuits[j - 1];
|
|
927
|
+
}
|
|
928
|
+
else if (typeof pump !== 'undefined') sys.pumps.removeItemById(pump.id);
|
|
929
|
+
}
|
|
930
930
|
public static decodeRemote(remoteDataArray) {
|
|
931
931
|
if (sys.controllerType === ControllerType.EasyTouch) {
|
|
932
932
|
|
|
@@ -980,11 +980,11 @@ class Controller {
|
|
|
980
980
|
remote6.button3 = remote.button8;
|
|
981
981
|
remote6.button4 = remote.button9;
|
|
982
982
|
if (!remote5.button1 && !remote5.button2 && !remote5.button3 && !remote5.button4) remote5.isActive = false;
|
|
983
|
-
|
|
984
|
-
|
|
983
|
+
else remote5.isActive = true;
|
|
984
|
+
|
|
985
985
|
if (!remote6.button1 && !remote6.button2 && !remote6.button3 && !remote6.button4) remote6.isActive = false;
|
|
986
|
-
|
|
987
|
-
|
|
986
|
+
else remote6.isActive = true;
|
|
987
|
+
|
|
988
988
|
}
|
|
989
989
|
else {
|
|
990
990
|
remote5.isActive = remote6.isActive = false;
|
|
@@ -1066,43 +1066,43 @@ class Controller {
|
|
|
1066
1066
|
}
|
|
1067
1067
|
|
|
1068
1068
|
}
|
|
1069
|
-
public static async decodePumpAsync(pDataArr: any
|
|
1070
|
-
pDataArr.forEach(async (pData, idx)=>{
|
|
1069
|
+
public static async decodePumpAsync(pDataArr: any) {
|
|
1070
|
+
pDataArr.forEach(async (pData, idx) => {
|
|
1071
1071
|
await sys.board.pumps.setPumpAsync(pData, false);
|
|
1072
1072
|
})
|
|
1073
1073
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
}
|
|
1074
|
+
public static async decodePumpStatusAsync(id: number, slpump: SLPumpStatusData) {
|
|
1075
|
+
/* {
|
|
1076
|
+
pumpCircuits: [
|
|
1077
|
+
{ circuitId: 6,speed: 2000,isRPMs: true, },
|
|
1078
|
+
{ circuitId: 8, speed:2700,isRPMs: true, },
|
|
1079
|
+
{ circuitId: 2,speed: 2710,isRPMs: true, },
|
|
1080
|
+
{ circuitId: 2,speed:1000, isRPMs: true,},
|
|
1081
|
+
{ circuitId: 5,speed:2830, isRPMs: true,},
|
|
1082
|
+
{ circuitId: 0,speed: 30,isRPMs: false,},
|
|
1083
|
+
{ circuitId: 0,speed: 30,isRPMs: false,},
|
|
1084
|
+
{ circuitId: 0,speed: 30,isRPMs: false,},
|
|
1085
|
+
],
|
|
1086
|
+
pumpType: 4,
|
|
1087
|
+
isRunning: false,
|
|
1088
|
+
pumpWatts: 0,
|
|
1089
|
+
pumpRPMs: 0,
|
|
1090
|
+
pumpUnknown1: 0,
|
|
1091
|
+
pumpGPMs: 0,
|
|
1092
|
+
pumpUnknown2: 255,
|
|
1093
|
+
}
|
|
1094
|
+
*/
|
|
1095
|
+
// RKS: 05-07-23 - This process of getting the pump by its id is flawed. We need to pull this information by its address.
|
|
1096
|
+
//let pstate = state.pumps.getItemById(id);
|
|
1097
|
+
let pstate = state.pumps.find(x => x.address === 95 + id);
|
|
1098
|
+
if (typeof pstate !== 'undefined') {
|
|
1099
|
+
pstate.watts = slpump.pumpWatts;
|
|
1100
|
+
pstate.rpm = slpump.pumpRPMs;
|
|
1101
|
+
pstate.flow = slpump.pumpGPMs === 255 ? 0 : slpump.pumpGPMs;
|
|
1102
|
+
pstate.command = (pstate.rpm > 0 || pstate.watts > 0) ? 10 : 0;
|
|
1103
|
+
state.emitEquipmentChanges();
|
|
1105
1104
|
}
|
|
1105
|
+
}
|
|
1106
1106
|
public static async decodeSchedules(slrecurring: SLScheduleData, slrunonce: SLScheduleData) {
|
|
1107
1107
|
/* reccuring schedules: [{"scheduleId":1,"circuitId":6,"startTime":"1800","stopTime":"0700","dayMask":127,"flags":0,"heatCmd":4,"heatSetPoint":70,"days":["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]},
|
|
1108
1108
|
|
|
@@ -1111,18 +1111,17 @@ class Controller {
|
|
|
1111
1111
|
Run once schedules: [{"scheduleId":12,"circuitId":6,"startTime":"0800","stopTime":"1100","dayMask":1,"flags":1,"heatCmd":4,"heatSetPoint":70,"days":["Mon"]},{"scheduleId":13,"circuitId":6,"startTime":"0800","stopTime":"1100","dayMask":1,"flags":1,"heatCmd":4,"heatSetPoint":70,"days":["Mon"]}] */
|
|
1112
1112
|
|
|
1113
1113
|
for (let i = 0; i < slrecurring.data.length; i++) {
|
|
1114
|
-
let slsched = slrecurring[i];
|
|
1115
|
-
let data = {
|
|
1116
|
-
id: slsched.scheduleId,
|
|
1117
|
-
circuit: slsched.circuitId,
|
|
1118
|
-
startTime: Math.floor(slsched.startTime / 100) * 60 + slsched.startTime % 100,
|
|
1119
|
-
endTime: Math.floor(slsched.stopTime / 100) * 60 + slsched.stopTime % 100,
|
|
1120
|
-
scheduleDays: slsched.dayMask,
|
|
1121
|
-
changeHeatSetPoint: slsched.heatCmd > 0,
|
|
1122
|
-
heatSetPoint: slsched.heatSetPoint,
|
|
1123
|
-
schedType: 128 // recurring
|
|
1124
|
-
}
|
|
1114
|
+
let slsched = slrecurring.data[i];
|
|
1125
1115
|
try {
|
|
1116
|
+
let data = {
|
|
1117
|
+
circuit: slsched.circuitId,
|
|
1118
|
+
startTime: Math.floor(parseInt(slsched.startTime, 10) / 100) * 60 + parseInt(slsched.startTime, 10) % 100,
|
|
1119
|
+
endTime: Math.floor(parseInt(slsched.stopTime, 10) / 100) * 60 + parseInt(slsched.stopTime, 10) % 100,
|
|
1120
|
+
scheduleDays: slsched.dayMask,
|
|
1121
|
+
changeHeatSetPoint: slsched.heatCmd > 0,
|
|
1122
|
+
heatSetPoint: slsched.heatSetPoint,
|
|
1123
|
+
schedType: 128 // recurring
|
|
1124
|
+
}
|
|
1126
1125
|
await sys.board.schedules.setScheduleAsync(data, false)
|
|
1127
1126
|
} catch (err) {
|
|
1128
1127
|
logger.error(`Error setting schedule ${slsched.scheduleId}. ${err.message}`);
|
|
@@ -1130,18 +1129,18 @@ class Controller {
|
|
|
1130
1129
|
}
|
|
1131
1130
|
for (let i = 0; i < slrunonce.data.length; i++) {
|
|
1132
1131
|
let slsched = slrunonce.data[i];
|
|
1133
|
-
let data = {
|
|
1134
|
-
id: slsched.scheduleId,
|
|
1135
|
-
circuit: slsched.circuitId,
|
|
1136
|
-
// start and stop come in as military time string
|
|
1137
|
-
startTime: parseInt(slsched.startTime, 10),
|
|
1138
|
-
endTime: parseInt(slsched.stopTime, 10),
|
|
1139
|
-
scheduleDays: slsched.dayMask,
|
|
1140
|
-
changeHeatSetPoint: slsched.heatCmd > 0,
|
|
1141
|
-
heatSetPoint: slsched.heatSetPoint,
|
|
1142
|
-
schedType: 0 // runonce
|
|
1143
|
-
}
|
|
1144
1132
|
try {
|
|
1133
|
+
let data = {
|
|
1134
|
+
id: slsched.scheduleId,
|
|
1135
|
+
circuit: slsched.circuitId,
|
|
1136
|
+
// start and stop come in as military time string
|
|
1137
|
+
startTime: parseInt(slsched.startTime, 10),
|
|
1138
|
+
endTime: parseInt(slsched.stopTime, 10),
|
|
1139
|
+
scheduleDays: slsched.dayMask,
|
|
1140
|
+
changeHeatSetPoint: slsched.heatCmd > 0,
|
|
1141
|
+
heatSetPoint: slsched.heatSetPoint,
|
|
1142
|
+
schedType: 0 // runonce
|
|
1143
|
+
}
|
|
1145
1144
|
await sys.board.schedules.setScheduleAsync(data, false);
|
|
1146
1145
|
sys.board.system.setTZ();
|
|
1147
1146
|
} catch (err) {
|
|
@@ -1607,23 +1606,23 @@ export class SLController extends SLCommands {
|
|
|
1607
1606
|
const spaCommand: Remote = sys.remotes.getItemById(8).get();
|
|
1608
1607
|
let alarm = 0;
|
|
1609
1608
|
|
|
1610
|
-
switch (eq){
|
|
1609
|
+
switch (eq) {
|
|
1611
1610
|
case 'misc': {
|
|
1612
|
-
|
|
1611
|
+
misc = extend({}, true, misc, obj);
|
|
1613
1612
|
break;
|
|
1614
1613
|
}
|
|
1615
1614
|
case 'lightGroup': {
|
|
1616
|
-
|
|
1615
|
+
lightGroup = extend({}, true, lightGroup, obj);
|
|
1617
1616
|
break;
|
|
1618
1617
|
}
|
|
1619
|
-
case 'pump':{
|
|
1620
|
-
let idx = pumps.findIndex(el=>{console.log(el.id);return el.id === obj.id;})
|
|
1618
|
+
case 'pump': {
|
|
1619
|
+
let idx = pumps.findIndex(el => { console.log(el.id); return el.id === obj.id; })
|
|
1621
1620
|
if (idx >= 0) pumps = extend({}, true, pumps[idx], obj);
|
|
1622
1621
|
else return Promise.reject(`Screenlogic: No pump found by that id: ${obj}`);
|
|
1623
1622
|
break;
|
|
1624
1623
|
}
|
|
1625
1624
|
case 'heater': {
|
|
1626
|
-
let idx = heaters.findIndex(el=>{console.log(el.id);return el.id === obj.id;})
|
|
1625
|
+
let idx = heaters.findIndex(el => { console.log(el.id); return el.id === obj.id; })
|
|
1627
1626
|
if (idx >= 0) heaters = extend({}, true, heaters[idx], obj);
|
|
1628
1627
|
else return Promise.reject(`Screenlogic: No pump found by that id: ${obj}`);
|
|
1629
1628
|
break;
|
|
@@ -1646,7 +1645,7 @@ export class SLController extends SLCommands {
|
|
|
1646
1645
|
// await this._unit.equipment.setEquipmentConfigurationAsync(data);
|
|
1647
1646
|
}
|
|
1648
1647
|
|
|
1649
|
-
public async setSystemTime(){
|
|
1648
|
+
public async setSystemTime() {
|
|
1650
1649
|
try {
|
|
1651
1650
|
let sysTime = await this._unit.equipment.setSystemTimeAsync(state.time.toDate(), sys.general.options.adjustDST);
|
|
1652
1651
|
logger.silly(`Screenlogic:set time result: ${sysTime}`);
|
|
@@ -1654,7 +1653,7 @@ export class SLController extends SLCommands {
|
|
|
1654
1653
|
return Promise.reject(new InvalidOperationError('Unable to set system time.', error.message));
|
|
1655
1654
|
}
|
|
1656
1655
|
}
|
|
1657
|
-
public async setCustomName(idx: number, name: string){
|
|
1656
|
+
public async setCustomName(idx: number, name: string) {
|
|
1658
1657
|
try {
|
|
1659
1658
|
let ack = await this._unit.equipment.setCustomNameAsync(idx, name);
|
|
1660
1659
|
logger.silly(`Screenlogic:set custom name result: ${JSON.stringify(ack)}`);
|
|
@@ -105,7 +105,7 @@ export class PumpStateMessage {
|
|
|
105
105
|
pump.mode = msg.extractPayloadByte(1);
|
|
106
106
|
pump.driveState = msg.extractPayloadByte(2);
|
|
107
107
|
pump.watts = (msg.extractPayloadByte(3) * 256) + msg.extractPayloadByte(4);
|
|
108
|
-
pump.rpm = (typeof ptype !== 'undefined' && ptype.maxSpeed > 0) ? (msg.extractPayloadByte(5) * 256) + msg.extractPayloadByte(6) : 0;
|
|
108
|
+
pump.rpm = (typeof ptype !== 'undefined' && (ptype.maxSpeed > 0 || ptype.name === 'vf')) ? (msg.extractPayloadByte(5) * 256) + msg.extractPayloadByte(6) : 0;
|
|
109
109
|
pump.flow = (typeof ptype !== 'undefined' && ptype.maxFlow > 0) ? msg.extractPayloadByte(7) : 0;
|
|
110
110
|
pump.ppc = msg.extractPayloadByte(8);
|
|
111
111
|
pump.status = (msg.extractPayloadByte(11) * 256) + msg.extractPayloadByte(12); // 16-bits of error codes.
|
|
@@ -158,17 +158,22 @@ export class NixieCircuit extends NixieEquipment {
|
|
|
158
158
|
}
|
|
159
159
|
protected async setIntelliBriteThemeAsync(cstate: CircuitState, theme: any): Promise<InterfaceServerResponse> {
|
|
160
160
|
let arr = [];
|
|
161
|
-
if (cstate.isOn) arr.push({ isOn: false, timeout: 1000 });
|
|
162
161
|
let count = typeof theme !== 'undefined' && theme.sequence ? theme.sequence : 0;
|
|
163
|
-
|
|
162
|
+
|
|
163
|
+
// Removing this. No need to turn the light off first. We actually need it on to start the sequence for theme setting to work correctly when the light is starting from the off state.
|
|
164
|
+
// if (cstate.isOn) arr.push({ isOn: false, timeout: 1000 });
|
|
165
|
+
|
|
166
|
+
// Start the sequence of off/on after the light is on.
|
|
167
|
+
arr.push({ isOn: true, timeout: 100 });
|
|
164
168
|
for (let i = 0; i < count; i++) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
arr.push({ isOn: false, timeout: 100 });
|
|
168
|
-
}
|
|
169
|
-
else arr.push({ isOn: true, timeout: 1000 });
|
|
169
|
+
arr.push({ isOn: false, timeout: 100 });
|
|
170
|
+
arr.push({ isOn: true, timeout: 100 });
|
|
170
171
|
}
|
|
171
|
-
|
|
172
|
+
// Ensure light stays on long enough for the theme to stick (required for light group theme setting to function correctly).
|
|
173
|
+
// 2s was too short.
|
|
174
|
+
arr.push({ isOn: true, timeout: 3000 });
|
|
175
|
+
|
|
176
|
+
logger.debug(arr);
|
|
172
177
|
let res = await NixieEquipment.putDeviceService(this.circuit.connectionId, `/state/device/${this.circuit.deviceBinding}`, arr, 60000);
|
|
173
178
|
// Even though we ended with on we need to make sure that the relay stays on now that we are done.
|
|
174
179
|
if (!res.error) {
|
|
@@ -771,9 +771,13 @@ export class NixiePumpVF extends NixiePumpRS485 {
|
|
|
771
771
|
// When we are 0 then it sends 4[255], 6[4], 5[6]
|
|
772
772
|
// When we are not 0 then it sends 4[255], 6[10], 5[6], 1[flow]
|
|
773
773
|
if (!this.closing) await this.setPumpToRemoteControlAsync(); // Action 4
|
|
774
|
-
if (!this.closing) await this.setDriveStateAsync(); // Action 6
|
|
775
|
-
if (!this.closing) await this.setPumpFeatureAsync(this._targetSpeed > 0 ? 6 : undefined); // Action 5
|
|
776
774
|
if (!this.closing && this._targetSpeed > 0) await this.setPumpGPMAsync(); // Action 1
|
|
775
|
+
if (!this.closing && this._targetSpeed > 0) await this.setPumpFeatureAsync(6); // Action 5
|
|
776
|
+
// RKS: 07-21-24 - This used to send an empty payload when the pump should be off. For VF pumps it
|
|
777
|
+
// appears that not setting the feature or target flow will set the pump off when it gets to
|
|
778
|
+
// the drive state.
|
|
779
|
+
//if (!this.closing) await this.setPumpFeatureAsync(this._targetSpeed > 0 ? 6 : undefined); // Action 5
|
|
780
|
+
if (!this.closing) await this.setDriveStateAsync(); // Action 6
|
|
777
781
|
if (!this.closing) await setTimeout(200);
|
|
778
782
|
if (!this.closing) await this.requestPumpStatusAsync(); // Action 7
|
|
779
783
|
}
|
package/package.json
CHANGED
package/.docker/Dockerfile.armv6
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# Use a base image compatible with ARMv6 architecture
|
|
2
|
-
FROM arm32v6/node:14-alpine
|
|
3
|
-
|
|
4
|
-
# Install necessary build dependencies
|
|
5
|
-
RUN apk add --no-cache make gcc g++ python3 linux-headers udev tzdata git
|
|
6
|
-
|
|
7
|
-
# Set the working directory
|
|
8
|
-
WORKDIR /app
|
|
9
|
-
|
|
10
|
-
# Copy package.json and package-lock.json
|
|
11
|
-
COPY package*.json ./
|
|
12
|
-
|
|
13
|
-
# Install dependencies (both development and production)
|
|
14
|
-
RUN npm ci
|
|
15
|
-
|
|
16
|
-
# Copy the rest of the application
|
|
17
|
-
COPY . .
|
|
18
|
-
|
|
19
|
-
# Build the application
|
|
20
|
-
RUN npm run build
|
|
21
|
-
|
|
22
|
-
# Set environment variables
|
|
23
|
-
ENV NODE_ENV=production
|
|
24
|
-
|
|
25
|
-
# Expose the port (if applicable)
|
|
26
|
-
EXPOSE 4200
|
|
27
|
-
|
|
28
|
-
# Command to run the application
|
|
29
|
-
CMD ["node", "dist/app.js"]
|
package/.docker/Dockerfile.armv7
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# Use a base image compatible with ARMv7 architecture
|
|
2
|
-
FROM arm32v7/node:14-alpine
|
|
3
|
-
|
|
4
|
-
# Install necessary build dependencies
|
|
5
|
-
RUN apk add --no-cache make gcc g++ python3 linux-headers udev tzdata git
|
|
6
|
-
|
|
7
|
-
# Set the working directory
|
|
8
|
-
WORKDIR /app
|
|
9
|
-
|
|
10
|
-
# Copy package.json and package-lock.json
|
|
11
|
-
COPY package*.json ./
|
|
12
|
-
|
|
13
|
-
# Install dependencies (both development and production)
|
|
14
|
-
RUN npm ci
|
|
15
|
-
|
|
16
|
-
# Copy the rest of the application
|
|
17
|
-
COPY . .
|
|
18
|
-
|
|
19
|
-
# Build the application
|
|
20
|
-
RUN npm run build
|
|
21
|
-
|
|
22
|
-
# Set environment variables
|
|
23
|
-
ENV NODE_ENV=production
|
|
24
|
-
|
|
25
|
-
# Expose the port (if applicable)
|
|
26
|
-
EXPOSE 4200
|
|
27
|
-
|
|
28
|
-
# Command to run the application
|
|
29
|
-
CMD ["node", "dist/app.js"]
|
package/.docker/Dockerfile.linux
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# Use a Linux-based image as the build stage for the first application
|
|
2
|
-
FROM node:lts-alpine AS build-njspc
|
|
3
|
-
|
|
4
|
-
# Install necessary build dependencies
|
|
5
|
-
RUN apk add --no-cache make gcc g++ python3 linux-headers udev tzdata
|
|
6
|
-
|
|
7
|
-
# Create the app directory and set ownership for the first application
|
|
8
|
-
RUN mkdir -p /app/nodejs-poolcontroller && chown node:node /app/nodejs-poolcontroller
|
|
9
|
-
|
|
10
|
-
# Set the working directory for the first application
|
|
11
|
-
WORKDIR /app/nodejs-poolcontroller
|
|
12
|
-
|
|
13
|
-
# Copy the source code and necessary files for the first application
|
|
14
|
-
COPY ./nodejs-poolcontroller/defaultConfig.json ./config.json
|
|
15
|
-
COPY ./nodejs-poolcontroller ./
|
|
16
|
-
COPY ./.docker/ecosystem.config.js ./ecosystem.config.js
|
|
17
|
-
|
|
18
|
-
# Install dependencies and build the first application
|
|
19
|
-
RUN npm ci
|
|
20
|
-
RUN npm run build
|
|
21
|
-
|
|
22
|
-
# Second stage for the second application
|
|
23
|
-
FROM node:lts-alpine AS build-njspc-dp
|
|
24
|
-
|
|
25
|
-
# Create the app directory and set ownership for the second application
|
|
26
|
-
RUN mkdir -p /app/nodejs-poolcontroller-dashpanel && chown node:node /app/nodejs-poolcontroller-dashpanel
|
|
27
|
-
|
|
28
|
-
# Set the working directory for the second application
|
|
29
|
-
WORKDIR /app/nodejs-poolcontroller-dashpanel
|
|
30
|
-
|
|
31
|
-
# Copy the source code and necessary files for the second application
|
|
32
|
-
COPY ./nodejs-poolcontroller-dashpanel ./
|
|
33
|
-
|
|
34
|
-
# Install dependencies and build the second application
|
|
35
|
-
RUN npm ci
|
|
36
|
-
RUN npm run build
|
|
37
|
-
|
|
38
|
-
# Fourth stage for the final combined image
|
|
39
|
-
FROM node:lts-alpine AS final
|
|
40
|
-
|
|
41
|
-
# Install PM2 globally
|
|
42
|
-
RUN npm install pm2 -g
|
|
43
|
-
|
|
44
|
-
# Create the app directory and set ownership
|
|
45
|
-
RUN mkdir -p /app && chown node:node /app
|
|
46
|
-
|
|
47
|
-
# Set the working directory for the final combined image
|
|
48
|
-
WORKDIR /app
|
|
49
|
-
|
|
50
|
-
# Copy built applications from the previous stages into the final image
|
|
51
|
-
COPY --from=build-njspc /app/nodejs-poolcontroller ./nodejs-poolcontroller
|
|
52
|
-
COPY --from=build-njspc-dp /app/nodejs-poolcontroller-dashpanel ./nodejs-poolcontroller-dashpanel
|
|
53
|
-
# COPY --from=build-rem /app/relayEquipmentManager ./relayEquipmentManager
|
|
54
|
-
|
|
55
|
-
# Copy the ecosystem configuration file from the build stage
|
|
56
|
-
COPY --from=build-njspc /app/nodejs-poolcontroller/ecosystem.config.js ./ecosystem.config.js
|
|
57
|
-
|
|
58
|
-
# Expose any necessary ports
|
|
59
|
-
EXPOSE 4200 5150
|
|
60
|
-
|
|
61
|
-
# Define the command to run both applications using PM2
|
|
62
|
-
CMD ["pm2-runtime", "start", "ecosystem.config.js"]
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# Use a Windows-based image as the build stage
|
|
2
|
-
FROM mcr.microsoft.com/windows/servercore:ltsc2019 AS build
|
|
3
|
-
|
|
4
|
-
# Set the working directory
|
|
5
|
-
WORKDIR C:\app
|
|
6
|
-
|
|
7
|
-
# Copy package.json and package-lock.json files
|
|
8
|
-
COPY package*.json ./
|
|
9
|
-
COPY defaultConfig.json config.json
|
|
10
|
-
|
|
11
|
-
# Install Node.js
|
|
12
|
-
RUN curl -sL https://nodejs.org/dist/v14.17.6/node-v14.17.6-x64.msi -o node.msi
|
|
13
|
-
RUN msiexec /i node.msi /quiet
|
|
14
|
-
|
|
15
|
-
# Install npm dependencies
|
|
16
|
-
RUN npm ci
|
|
17
|
-
|
|
18
|
-
# Copy the rest of the application files
|
|
19
|
-
COPY . .
|
|
20
|
-
|
|
21
|
-
# Build the application
|
|
22
|
-
RUN npm run build
|
|
23
|
-
|
|
24
|
-
# Second stage for the production image
|
|
25
|
-
FROM mcr.microsoft.com/windows/servercore:ltsc2019 as prod
|
|
26
|
-
|
|
27
|
-
# Install git
|
|
28
|
-
RUN powershell -Command "Invoke-WebRequest -Uri https://github.com/git-for-windows/git/releases/download/v2.33.1.windows.1/Git-2.33.1-64-bit.exe -OutFile git.exe" && .\git.exe /VERYSILENT /NORESTART
|
|
29
|
-
|
|
30
|
-
# Create the app directory
|
|
31
|
-
RUN mkdir C:\app
|
|
32
|
-
|
|
33
|
-
# Set the working directory
|
|
34
|
-
WORKDIR C:\app
|
|
35
|
-
|
|
36
|
-
# Copy built application from the build stage
|
|
37
|
-
COPY --from=build C:\app .
|
|
38
|
-
|
|
39
|
-
# Set environment variables
|
|
40
|
-
ENV NODE_ENV=production
|
|
41
|
-
|
|
42
|
-
# Define the entrypoint
|
|
43
|
-
CMD ["node", "dist/app.js"]
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
version: '3.8'
|
|
2
|
-
|
|
3
|
-
services:
|
|
4
|
-
poolcontroller:
|
|
5
|
-
image: tagyoureit/nodejs-poolcontroller:latest
|
|
6
|
-
container_name: poolcontroller
|
|
7
|
-
restart: always
|
|
8
|
-
group_add:
|
|
9
|
-
- dialout
|
|
10
|
-
devices:
|
|
11
|
-
- /dev/ttyUSB0
|
|
12
|
-
ports:
|
|
13
|
-
- "4200:4200"
|
|
14
|
-
volumes:
|
|
15
|
-
- /data/poolcontroller/config.json:/app/nodejs-poolcontroller/config.json
|
|
16
|
-
- /data/poolcontroller/data:/app/nodejs-poolcontroller/data
|
|
17
|
-
- /data/poolcontroller/logs:/app/nodejs-poolcontroller/logs
|
|
18
|
-
poolcontroller-dashpanel:
|
|
19
|
-
restart: always
|
|
20
|
-
container_name: poolcontroller-dashpanel
|
|
21
|
-
ports:
|
|
22
|
-
- "5150:5150"
|
|
23
|
-
volumes:
|
|
24
|
-
- /data/poolcontroller-dashpanel/config.json:/app/nodejs-poolcontroller-dashpanel/config.json
|
|
25
|
-
image: rstrouse/nodejs-poolcontroller-dashpanel:latest
|
|
26
|
-
depends_on:
|
|
27
|
-
- poolcontroller
|
|
28
|
-
|
|
29
|
-
# poolcontroller-armv7:
|
|
30
|
-
# image: tagyoureit/nodejs-poolcontroller-armv7:latest
|
|
31
|
-
# container_name: poolcontroller-armv7
|
|
32
|
-
# restart: always
|
|
33
|
-
# ports:
|
|
34
|
-
# - "4200:4200"
|
|
35
|
-
# volumes:
|
|
36
|
-
# - /data/poolcontroller/config.json:/app/config.json
|
|
37
|
-
# - /data/poolcontroller/data:/app/data
|
|
38
|
-
|
|
39
|
-
# poolcontroller-armv6:
|
|
40
|
-
# image: tagyoureit/nodejs-poolcontroller-armv6:latest
|
|
41
|
-
# container_name: poolcontroller-armv6
|
|
42
|
-
# restart: always
|
|
43
|
-
# ports:
|
|
44
|
-
# - "4200:4200"
|
|
45
|
-
# volumes:
|
|
46
|
-
# - /data/poolcontroller/config.json:/app/config.json
|
|
47
|
-
# - /data/poolcontroller/data:/app/data
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
apps: [
|
|
3
|
-
{
|
|
4
|
-
name: "dashPanel",
|
|
5
|
-
script: "npm",
|
|
6
|
-
args: ["start"],
|
|
7
|
-
cwd: "/app/nodejs-poolcontroller-dashpanel",
|
|
8
|
-
restart_delay: 10000,
|
|
9
|
-
watch: [
|
|
10
|
-
"pages",
|
|
11
|
-
"scripts",
|
|
12
|
-
"server",
|
|
13
|
-
"package.json"
|
|
14
|
-
],
|
|
15
|
-
watch_delay: 5000,
|
|
16
|
-
kill_timeout: 15000
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
name: "njsPC",
|
|
20
|
-
script: "npm",
|
|
21
|
-
args: ["start"],
|
|
22
|
-
cwd: "/app/nodejs-poolcontroller",
|
|
23
|
-
restart_delay: 10000,
|
|
24
|
-
watch: [
|
|
25
|
-
"config",
|
|
26
|
-
"controller",
|
|
27
|
-
"logger",
|
|
28
|
-
"web",
|
|
29
|
-
"package.json"
|
|
30
|
-
],
|
|
31
|
-
watch_delay: 5000,
|
|
32
|
-
kill_timeout: 15000
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
name: Publish Docker Image - Windows
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- docker
|
|
7
|
-
workflow_dispatch:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
build-and-push-windows:
|
|
12
|
-
runs-on: windows-latest
|
|
13
|
-
|
|
14
|
-
steps:
|
|
15
|
-
- name: Checkout code
|
|
16
|
-
uses: actions/checkout@v4
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
# Add support for more platforms with QEMU (optional)
|
|
20
|
-
# https://github.com/docker/setup-qemu-action
|
|
21
|
-
name: Set up QEMU
|
|
22
|
-
uses: docker/setup-qemu-action@v3
|
|
23
|
-
-
|
|
24
|
-
name: Set up Docker Buildx
|
|
25
|
-
uses: docker/setup-buildx-action@v3
|
|
26
|
-
|
|
27
|
-
- name: Login to Docker Hub
|
|
28
|
-
uses: docker/login-action@v3
|
|
29
|
-
with:
|
|
30
|
-
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
31
|
-
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
32
|
-
|
|
33
|
-
- name: Build and push Windows Docker image
|
|
34
|
-
uses: docker/build-push-action@v3
|
|
35
|
-
with:
|
|
36
|
-
context: .
|
|
37
|
-
file: ./Dockerfile.windows
|
|
38
|
-
push: true
|
|
39
|
-
tags: |
|
|
40
|
-
tagyoureit/nodejs-poolcontroller:windows-latest
|
|
41
|
-
platforms: windows/amd64
|