nodejs-poolcontroller 8.1.2 → 8.4.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.
Files changed (106) hide show
  1. package/.eslintrc.json +36 -36
  2. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +84 -84
  3. package/.github/ISSUE_TEMPLATE/2-docs.md +12 -12
  4. package/.github/ISSUE_TEMPLATE/3-proposal.md +28 -28
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -8
  6. package/.github/copilot-instructions.md +63 -0
  7. package/.github/workflows/ghcr-publish.yml +67 -0
  8. package/AGENTS.md +597 -0
  9. package/CONTRIBUTING.md +74 -74
  10. package/Changelog +292 -257
  11. package/Dockerfile +62 -19
  12. package/Gruntfile.js +40 -40
  13. package/LICENSE +661 -661
  14. package/README.md +318 -191
  15. package/anslq25/MessagesMock.ts +221 -221
  16. package/anslq25/boards/MockBoardFactory.ts +49 -49
  17. package/anslq25/boards/MockEasyTouchBoard.ts +696 -696
  18. package/anslq25/boards/MockSystemBoard.ts +216 -216
  19. package/anslq25/chemistry/MockChlorinator.ts +98 -98
  20. package/anslq25/pumps/MockPump.ts +83 -83
  21. package/app.ts +115 -115
  22. package/config/Config.ts +57 -7
  23. package/config/VersionCheck.ts +63 -35
  24. package/controller/Constants.ts +809 -805
  25. package/controller/Equipment.ts +2688 -2664
  26. package/controller/Errors.ts +181 -181
  27. package/controller/Lockouts.ts +549 -549
  28. package/controller/State.ts +3738 -3690
  29. package/controller/boards/AquaLinkBoard.ts +1003 -1003
  30. package/controller/boards/BoardFactory.ts +53 -53
  31. package/controller/boards/EasyTouchBoard.ts +3202 -3202
  32. package/controller/boards/IntelliCenterBoard.ts +4393 -3899
  33. package/controller/boards/IntelliComBoard.ts +69 -69
  34. package/controller/boards/IntelliTouchBoard.ts +382 -382
  35. package/controller/boards/NixieBoard.ts +1944 -1929
  36. package/controller/boards/SunTouchBoard.ts +400 -400
  37. package/controller/boards/SystemBoard.ts +5268 -5268
  38. package/controller/comms/Comms.ts +1272 -1214
  39. package/controller/comms/ScreenLogic.ts +1665 -1665
  40. package/controller/comms/messages/Messages.ts +1433 -1243
  41. package/controller/comms/messages/config/ChlorinatorMessage.ts +5 -0
  42. package/controller/comms/messages/config/CircuitGroupMessage.ts +0 -0
  43. package/controller/comms/messages/config/CircuitMessage.ts +0 -0
  44. package/controller/comms/messages/config/ConfigMessage.ts +6 -0
  45. package/controller/comms/messages/config/CoverMessage.ts +0 -0
  46. package/controller/comms/messages/config/CustomNameMessage.ts +31 -31
  47. package/controller/comms/messages/config/EquipmentMessage.ts +216 -210
  48. package/controller/comms/messages/config/ExternalMessage.ts +96 -10
  49. package/controller/comms/messages/config/FeatureMessage.ts +0 -0
  50. package/controller/comms/messages/config/GeneralMessage.ts +0 -0
  51. package/controller/comms/messages/config/HeaterMessage.ts +0 -0
  52. package/controller/comms/messages/config/IntellichemMessage.ts +0 -0
  53. package/controller/comms/messages/config/OptionsMessage.ts +194 -174
  54. package/controller/comms/messages/config/PumpMessage.ts +0 -0
  55. package/controller/comms/messages/config/RemoteMessage.ts +0 -0
  56. package/controller/comms/messages/config/ScheduleMessage.ts +401 -390
  57. package/controller/comms/messages/config/SecurityMessage.ts +0 -0
  58. package/controller/comms/messages/config/ValveMessage.ts +0 -0
  59. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +0 -0
  60. package/controller/comms/messages/status/EquipmentStateMessage.ts +1158 -822
  61. package/controller/comms/messages/status/HeaterStateMessage.ts +135 -135
  62. package/controller/comms/messages/status/IntelliChemStateMessage.ts +448 -448
  63. package/controller/comms/messages/status/IntelliValveStateMessage.ts +36 -36
  64. package/controller/comms/messages/status/PumpStateMessage.ts +0 -0
  65. package/controller/comms/messages/status/RegalModbusStateMessage.ts +411 -0
  66. package/controller/comms/messages/status/VersionMessage.ts +103 -41
  67. package/controller/nixie/Nixie.ts +173 -173
  68. package/controller/nixie/NixieEquipment.ts +104 -104
  69. package/controller/nixie/bodies/Body.ts +120 -120
  70. package/controller/nixie/bodies/Filter.ts +135 -135
  71. package/controller/nixie/chemistry/ChemController.ts +2724 -2724
  72. package/controller/nixie/chemistry/ChemDoser.ts +806 -806
  73. package/controller/nixie/chemistry/Chlorinator.ts +367 -367
  74. package/controller/nixie/circuits/Circuit.ts +478 -478
  75. package/controller/nixie/heaters/Heater.ts +834 -834
  76. package/controller/nixie/pumps/Pump.ts +1194 -996
  77. package/controller/nixie/schedules/Schedule.ts +401 -401
  78. package/controller/nixie/valves/Valve.ts +170 -170
  79. package/defaultConfig.json +352 -347
  80. package/docker-compose.yml +32 -0
  81. package/logger/DataLogger.ts +448 -448
  82. package/logger/Logger.ts +448 -436
  83. package/package.json +58 -60
  84. package/sendSocket.js +32 -32
  85. package/tsconfig.json +25 -25
  86. package/types/express-multer.d.ts +32 -0
  87. package/web/Server.ts +1937 -1927
  88. package/web/bindings/aqualinkD.json +559 -559
  89. package/web/bindings/influxDB.json +1066 -1066
  90. package/web/bindings/mqtt.json +721 -721
  91. package/web/bindings/mqttAlt.json +746 -746
  92. package/web/bindings/rulesManager.json +54 -54
  93. package/web/bindings/smartThings-Hubitat.json +31 -31
  94. package/web/bindings/valveRelays.json +20 -20
  95. package/web/bindings/vera.json +25 -25
  96. package/web/interfaces/baseInterface.ts +188 -188
  97. package/web/interfaces/httpInterface.ts +148 -148
  98. package/web/interfaces/influxInterface.ts +283 -283
  99. package/web/interfaces/mqttInterface.ts +695 -695
  100. package/web/interfaces/ruleInterface.ts +101 -87
  101. package/web/services/config/Config.ts +1063 -1053
  102. package/web/services/config/ConfigSocket.ts +0 -0
  103. package/web/services/state/State.ts +0 -0
  104. package/web/services/state/StateSocket.ts +0 -0
  105. package/web/services/utilities/Utilities.ts +233 -233
  106. package/.github/workflows/docker-publish-njsPC-linux.yml +0 -50
package/.eslintrc.json CHANGED
@@ -1,36 +1,36 @@
1
- {
2
- "env": {
3
- "es2021": true,
4
- "node": true
5
- },
6
- "extends": [
7
- "eslint:recommended",
8
- "plugin:@typescript-eslint/recommended"
9
- ],
10
- "parser": "@typescript-eslint/parser",
11
- "parserOptions": {
12
- "ecmaVersion": "latest",
13
- "sourceType": "module"
14
- },
15
- "plugins": [
16
- "@typescript-eslint"
17
- ],
18
- "rules": {
19
- "indent": [
20
- "error",
21
- "tab"
22
- ],
23
- "linebreak-style": [
24
- "error",
25
- "windows"
26
- ],
27
- "quotes": [
28
- "error",
29
- "single"
30
- ],
31
- "semi": [
32
- "error",
33
- "always"
34
- ]
35
- }
36
- }
1
+ {
2
+ "env": {
3
+ "es2021": true,
4
+ "node": true
5
+ },
6
+ "extends": [
7
+ "eslint:recommended",
8
+ "plugin:@typescript-eslint/recommended"
9
+ ],
10
+ "parser": "@typescript-eslint/parser",
11
+ "parserOptions": {
12
+ "ecmaVersion": "latest",
13
+ "sourceType": "module"
14
+ },
15
+ "plugins": [
16
+ "@typescript-eslint"
17
+ ],
18
+ "rules": {
19
+ "indent": [
20
+ "error",
21
+ "tab"
22
+ ],
23
+ "linebreak-style": [
24
+ "error",
25
+ "windows"
26
+ ],
27
+ "quotes": [
28
+ "error",
29
+ "single"
30
+ ],
31
+ "semi": [
32
+ "error",
33
+ "always"
34
+ ]
35
+ }
36
+ }
@@ -1,84 +1,84 @@
1
- name: "\U0001F41B Bug report"
2
- description: Create a report to help us improve
3
- title: '[BUG] '
4
- body:
5
- - type: markdown
6
- attributes:
7
- value: |
8
- Thank you for reporting an issue. Most issues can be more readily resolved by attaching a Packet Capture. Follow the instructions to complete a [packet capture](https://github.com/tagyoureit/nodejs-poolController/wiki/How-to-capture-all-packets-for-issue-resolution) and attach the resulting zip/log files.
9
-
10
- If you require more general support please file an start a discussion on our discussion board https://github.com/tagyoureit/nodejs-poolController/discussions
11
-
12
- Having trouble installing? Be sure to check out the wiki! https://github.com/tagyoureit/nodejs-poolController/wiki
13
-
14
- Please fill in as much of the form below as you're able.
15
- - type: input
16
- attributes:
17
- label: nodejs-poolController Version/commit
18
- description: can be viewed under dashPanel. Hamburger menu => System.
19
- validations:
20
- required: true
21
- - type: input
22
- attributes:
23
- label: nodejs-poolController-dashPanel Version/commit
24
- description: if applicable
25
- - type: input
26
- attributes:
27
- label: relayEquipmentManager Version/commit
28
- description: if applicable
29
- - type: input
30
- attributes:
31
- label: Node Version
32
- description: Output of `node -v`
33
- - type: input
34
- attributes:
35
- label: Platform
36
- description: |
37
- UNIX: output of `uname -a`
38
- Windows: output of `"$([Environment]::OSVersion | ForEach-Object VersionString) $(if ([Environment]::Is64BitOperatingSystem) { "x64" } else { "x86" })"` in PowerShell console
39
- - type: input
40
- attributes:
41
- label: RS485 Adapter
42
- description: Elfin? JBTek?
43
- - type: checkboxes
44
- attributes:
45
- label: Are you using Docker?
46
- options:
47
- - label: Yes.
48
- - type: input
49
- attributes:
50
- label: OCP
51
- description: Outdoor Control Panel. Eg EasyTouch2 8P, Intellicenter i5PS, none.
52
- placeholder: None / Nixie (standalone setup)
53
- - type: input
54
- attributes:
55
- label: Pump(s)
56
- description: Please list all pumps. EG Intelliflo 2 VST, Intelliflo VS
57
- placeholder: Intelliflo VS
58
- - type: input
59
- attributes:
60
- label: Chlorinator(s)
61
- description: Please list all chlorinators. EG Intellichlor IC-40, Aquarite, None
62
- placeholder: None
63
- - type: textarea
64
- attributes:
65
- label: What steps will reproduce the bug?
66
- description: Enter details about your bug, preferably a simple code snippet that can be run using `node` directly without installing third-party dependencies.
67
- validations:
68
- required: true
69
- - type: textarea
70
- attributes:
71
- label: What happens?
72
- description: If possible please provide textual output instead of screenshots.
73
- validations:
74
- required: true
75
- - type: textarea
76
- attributes:
77
- label: What should have happened?
78
- description: If possible please provide textual output instead of screenshots.
79
- validations:
80
- required: true
81
- - type: textarea
82
- attributes:
83
- label: Additional information
84
- description: Tell us anything else you think we should know.
1
+ name: "\U0001F41B Bug report"
2
+ description: Create a report to help us improve
3
+ title: '[BUG] '
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thank you for reporting an issue. Most issues can be more readily resolved by attaching a Packet Capture. Follow the instructions to complete a [packet capture](https://github.com/tagyoureit/nodejs-poolController/wiki/How-to-capture-all-packets-for-issue-resolution) and attach the resulting zip/log files.
9
+
10
+ If you require more general support please file an start a discussion on our discussion board https://github.com/tagyoureit/nodejs-poolController/discussions
11
+
12
+ Having trouble installing? Be sure to check out the wiki! https://github.com/tagyoureit/nodejs-poolController/wiki
13
+
14
+ Please fill in as much of the form below as you're able.
15
+ - type: input
16
+ attributes:
17
+ label: nodejs-poolController Version/commit
18
+ description: can be viewed under dashPanel. Hamburger menu => System.
19
+ validations:
20
+ required: true
21
+ - type: input
22
+ attributes:
23
+ label: nodejs-poolController-dashPanel Version/commit
24
+ description: if applicable
25
+ - type: input
26
+ attributes:
27
+ label: relayEquipmentManager Version/commit
28
+ description: if applicable
29
+ - type: input
30
+ attributes:
31
+ label: Node Version
32
+ description: Output of `node -v`
33
+ - type: input
34
+ attributes:
35
+ label: Platform
36
+ description: |
37
+ UNIX: output of `uname -a`
38
+ Windows: output of `"$([Environment]::OSVersion | ForEach-Object VersionString) $(if ([Environment]::Is64BitOperatingSystem) { "x64" } else { "x86" })"` in PowerShell console
39
+ - type: input
40
+ attributes:
41
+ label: RS485 Adapter
42
+ description: Elfin? JBTek?
43
+ - type: checkboxes
44
+ attributes:
45
+ label: Are you using Docker?
46
+ options:
47
+ - label: Yes.
48
+ - type: input
49
+ attributes:
50
+ label: OCP
51
+ description: Outdoor Control Panel. Eg EasyTouch2 8P, Intellicenter i5PS, none.
52
+ placeholder: None / Nixie (standalone setup)
53
+ - type: input
54
+ attributes:
55
+ label: Pump(s)
56
+ description: Please list all pumps. EG Intelliflo 2 VST, Intelliflo VS
57
+ placeholder: Intelliflo VS
58
+ - type: input
59
+ attributes:
60
+ label: Chlorinator(s)
61
+ description: Please list all chlorinators. EG Intellichlor IC-40, Aquarite, None
62
+ placeholder: None
63
+ - type: textarea
64
+ attributes:
65
+ label: What steps will reproduce the bug?
66
+ description: Enter details about your bug, preferably a simple code snippet that can be run using `node` directly without installing third-party dependencies.
67
+ validations:
68
+ required: true
69
+ - type: textarea
70
+ attributes:
71
+ label: What happens?
72
+ description: If possible please provide textual output instead of screenshots.
73
+ validations:
74
+ required: true
75
+ - type: textarea
76
+ attributes:
77
+ label: What should have happened?
78
+ description: If possible please provide textual output instead of screenshots.
79
+ validations:
80
+ required: true
81
+ - type: textarea
82
+ attributes:
83
+ label: Additional information
84
+ description: Tell us anything else you think we should know.
@@ -1,12 +1,12 @@
1
- ---
2
- name: 📚 Documentation
3
- about: Report an issue related to documentation
4
- ---
5
-
6
- ## 📚 Documentation
7
-
8
- (A clear and concise description of how the docs could be better, with links if possible)
9
-
10
- ### Have you read the [Contributing Guidelines on docs](https://github.com/serialport/node-serialport/blob/master/CONTRIBUTING.md#writing-documentation)?
11
-
12
- (Write your answer here.)
1
+ ---
2
+ name: 📚 Documentation
3
+ about: Report an issue related to documentation
4
+ ---
5
+
6
+ ## 📚 Documentation
7
+
8
+ (A clear and concise description of how the docs could be better, with links if possible)
9
+
10
+ ### Have you read the [Contributing Guidelines on docs](https://github.com/serialport/node-serialport/blob/master/CONTRIBUTING.md#writing-documentation)?
11
+
12
+ (Write your answer here.)
@@ -1,28 +1,28 @@
1
- ---
2
- name: 💥 Proposal / Feature
3
- about: Propose a non-trivial change or new feature for SerialPort
4
- ---
5
-
6
- ## 💥 Proposal
7
-
8
- ### What feature you'd like to see
9
-
10
- (A clear and concise description of what the proposal is.)
11
-
12
- ## Motivation
13
-
14
- (Please outline the motivation for the proposal. It's interesting knowing what people are working on and also could help community members make suggestions for work-arounds until the feature is built)
15
-
16
- ## Pitch
17
-
18
- (Please explain why this feature should be implemented and how it would be used.)
19
-
20
- <!--
21
- What happens if you skip this step?
22
-
23
- Someone will read your feature proposal and maybe will be able to help you,
24
- but it’s unlikely that it will get much attention from the team. Eventually,
25
- the issue will likely get closed in favor of issues that have better explanations
26
-
27
- Thanks for helping us help you!
28
- -->
1
+ ---
2
+ name: 💥 Proposal / Feature
3
+ about: Propose a non-trivial change or new feature for SerialPort
4
+ ---
5
+
6
+ ## 💥 Proposal
7
+
8
+ ### What feature you'd like to see
9
+
10
+ (A clear and concise description of what the proposal is.)
11
+
12
+ ## Motivation
13
+
14
+ (Please outline the motivation for the proposal. It's interesting knowing what people are working on and also could help community members make suggestions for work-arounds until the feature is built)
15
+
16
+ ## Pitch
17
+
18
+ (Please explain why this feature should be implemented and how it would be used.)
19
+
20
+ <!--
21
+ What happens if you skip this step?
22
+
23
+ Someone will read your feature proposal and maybe will be able to help you,
24
+ but it’s unlikely that it will get much attention from the team. Eventually,
25
+ the issue will likely get closed in favor of issues that have better explanations
26
+
27
+ Thanks for helping us help you!
28
+ -->
@@ -1,8 +1,8 @@
1
- blank_issues_enabled: false
2
- contact_links:
3
- - name: ⁉️ Need help with nodejs-poolController?
4
- url: https://github.com/tagyoureit/nodejs-poolController/discussions
5
- about: Please start a discussion before opening a bug.
6
- - name: Gitter
7
- url: https://gitter.im/nodejs-poolController/Lobby
8
- about: Legacy Gitter discussion forums
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: ⁉️ Need help with nodejs-poolController?
4
+ url: https://github.com/tagyoureit/nodejs-poolController/discussions
5
+ about: Please start a discussion before opening a bug.
6
+ - name: Gitter
7
+ url: https://gitter.im/nodejs-poolController/Lobby
8
+ about: Legacy Gitter discussion forums
@@ -0,0 +1,63 @@
1
+ # Copilot Project Instructions
2
+
3
+ Purpose: Help AI agents contribute effectively to nodejs-poolController (njsPC) with minimal ramp-up.
4
+
5
+ ## 1. Core Domain & Architecture
6
+ - Goal: Bridge Pentair / compatible pool automation equipment (RS-485 / ScreenLogic) to REST, WebSockets, MQTT, InfluxDB, Rules, and REM (Relay Equipment Manager) interfaces.
7
+ - Startup sequence (see `app.ts`): config.init -> logger.init -> sys.init -> state.init -> webApp.init -> conn.initAsync (RS485 / network) -> sys.start -> webApp.initAutoBackup -> sl.openAsync (ScreenLogic).
8
+ - Major layers:
9
+ 1. `config/Config.ts`: Loads/merges `defaultConfig.json` + `config.json`, watches disk, applies env overrides (POOL_*). Always mutate via `config.setSection()` / `config.updateAsync()`.
10
+ 2. `controller/`:
11
+ - `comms/Comms.ts` (RS485 transport) + `comms/messages/*` (protocol encode/decode) feeding message objects to system/state.
12
+ - `Equipment.ts` (`sys`): Aggregates boards, pumps, heaters, bodies, chemistry, schedules.
13
+ - `boards/*Board.ts` selected by `BoardFactory.fromControllerType()` (ControllerType enum) to encapsulate model-specific logic.
14
+ - `State.ts`: Higher-level computed/state cache (emits events to interfaces & persistence).
15
+ 3. `web/Server.ts`: Orchestrates multiple server/interface types (http/https/http2, mdns, ssdp, mqtt, influx, rule, rem). Each concrete server extends a ProtoServer pattern (see file) and exposes `emitToClients` / `emitToChannel`.
16
+ 4. `logger/Logger.ts`: Winston wrapper with packet & ScreenLogic capture, optional replay capture mode (`log.app.captureForReplay`).
17
+ - Data Flow: Raw bytes -> `Comms` -> `Messages` decode -> equipment/state mutation -> events -> `webApp.emitToChannel()` -> clients (dashPanel, bindings, MQTT, etc.).
18
+
19
+ ## 2. Key Conventions & Patterns
20
+ - Prefer calling exported singletons (`config`, `logger`, `sys`, `state`, `webApp`, `conn`) — they are initialized once in `app.ts`.
21
+ - Extend support for a new controller board: create `controller/boards/NewBoard.ts` implementing expected interface and add to `BoardFactory` switch.
22
+ - Adding an external interface: implement a server class similar to existing ones in `web/Server.ts` and register in `initInterfaces()` via `type` value in `web.interfaces` section of config.
23
+ - Configuration writes are async & debounced by a semaphore (`_isLoading`). Avoid rapid consecutive writes — batch changes before `setSection`.
24
+ - Logging packets: push through `logger.packet(msg)`; only log when `log.packet.enabled` or capture mode active. Don't bypass logger for protocol-level diagnostics.
25
+ - Use `utils.uuid()` for persistent IDs stored back into config (`web.servers.*` / `web.interfaces.*`).
26
+
27
+ ## 3. Build & Run Workflow
28
+ - Scripts (`package.json`): `npm start` = build (tsc) + run `dist/app.js`; `npm run start:cached` skips build (use only after prior successful build); `npm run build` or `watch` for development.
29
+ - Always rebuild after pulling if Typescript sources changed (common; master is live development).
30
+ - Minimum Node >=16 (see `engines`).
31
+ - Typical dev loop: edit TS -> `npm run build` (or `watch` in one terminal) -> `npm run start:cached` in another.
32
+
33
+ ## 4. Safe Change Guidelines (Project Specific)
34
+ - Never directly edit `config.json` structure assumptions without updating `defaultConfig.json` and migration logic if needed.
35
+ - When adding message types: place in proper `controller/comms/messages/{config|status}` folder; ensure decode populates strongly typed object consumed by equipment/state.
36
+ - Emitting to clients: prefer channel scoping with `webApp.emitToChannel(channel, evt, payload)` over broad `emitToClients` to reduce noise.
37
+ - Shutdown paths must await: see `stopAsync()` ordering in `app.ts`; replicate that order if introducing new long-lived resources.
38
+ - Packet capture integration: if adding new traffic sources, feed capture arrays so `logger.stopCaptureForReplayAsync()` includes them in backups.
39
+
40
+ ## 5. Extending / Examples
41
+ - Add new board: create file, implement constructor(system), override protocol handlers, add case in `BoardFactory`.
42
+ - Add new interface type: define class (e.g., `FooInterfaceServer`) patterned after `MqttInterfaceServer`; map `type: 'foo'` in config to new class in `initInterfaces` switch.
43
+ - Add env override: update `Config.getEnvVariables()` with POOL_* variable mapping.
44
+
45
+ ## 6. Debugging Tips
46
+ - Packet issues: enable `log.packet.logToConsole` & set `log.app.level` to `debug` or `silly` in `config.json` (or via capture mode) then rebuild & restart.
47
+ - Config reload: editing `config.json` on disk triggers fs watch; logger reinitializes log settings automatically.
48
+ - Network discovery problems: inspect `mdns` / `ssdp` sections in `web.servers` config; ensure correct interface binding (`ip` / `0.0.0.0`).
49
+
50
+ ## 7. Common Pitfalls
51
+ - Forgetting to rebuild after TS edits (leads to running stale `dist`).
52
+ - Mutating returned config objects directly after `getSection` (they are deep-cloned; you must re-set via `setSection`).
53
+ - Adding interface without persisting UUID: ensure `utils.uuid()` assigned when undefined.
54
+ - Logging floods: avoid tight loops writing directly to console; use logger buffering (`packet` flush timer) pattern.
55
+
56
+ ## 8. Contribution Checklist (Agent Focused)
57
+ 1. Identify layer (comms / equipment / state / interface / config / logging) impacted.
58
+ 2. Update or add unit-like logic in correct module; keep cross-layer boundaries (no UI assumptions in lower layers).
59
+ 3. Use existing singletons; avoid new global state without need.
60
+ 4. Validate build (`npm run build`) before proposing changes.
61
+ 5. Provide brief rationale in PR tying change to equipment behavior or integration capability.
62
+
63
+ Feedback welcome: clarify any unclear pattern or request examples to extend this guide.
@@ -0,0 +1,67 @@
1
+ name: Publish Docker Image - GHCR
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ tags:
8
+ - 'v*.*.*'
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ build-and-push:
13
+ runs-on: ubuntu-latest
14
+ permissions:
15
+ contents: read
16
+ packages: write
17
+ steps:
18
+ - name: Checkout
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Docker meta
22
+ id: meta
23
+ uses: docker/metadata-action@v5
24
+ with:
25
+ images: |
26
+ ghcr.io/${{ github.repository_owner }}/njspc
27
+ tags: |
28
+ type=ref,event=branch
29
+ type=ref,event=pr
30
+ type=semver,pattern={{version}}
31
+ type=semver,pattern={{major}}.{{minor}}
32
+ type=semver,pattern={{major}}
33
+ type=sha
34
+ type=raw,value=latest,enable={{is_default_branch}}
35
+ labels: |
36
+ org.opencontainers.image.source=${{ github.repository }}
37
+ org.opencontainers.image.revision=${{ github.sha }}
38
+ org.opencontainers.image.title=njspc
39
+ org.opencontainers.image.description=Pentair pool controller bridge (GHCR image)
40
+
41
+ - name: Set up QEMU
42
+ uses: docker/setup-qemu-action@v3
43
+
44
+ - name: Set up Docker Buildx
45
+ uses: docker/setup-buildx-action@v3
46
+
47
+ - name: Login to GHCR
48
+ uses: docker/login-action@v3
49
+ with:
50
+ registry: ghcr.io
51
+ username: ${{ github.actor }}
52
+ password: ${{ secrets.GITHUB_TOKEN }}
53
+
54
+ - name: Build and push
55
+ uses: docker/build-push-action@v6
56
+ with:
57
+ context: .
58
+ push: true
59
+ platforms: linux/amd64,linux/arm64,linux/arm/v7
60
+ tags: ${{ steps.meta.outputs.tags }}
61
+ labels: ${{ steps.meta.outputs.labels }}
62
+ cache-from: type=gha
63
+ cache-to: type=gha,mode=max
64
+
65
+ - name: Echo published tags
66
+ run: |
67
+ echo "Published: ${{ steps.meta.outputs.tags }}"