amaran-light-cli 1.1.2 → 1.3.6

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 (112) hide show
  1. package/CHANGELOG.md +44 -5
  2. package/README.md +94 -70
  3. package/dist/__tests__/autoCct.test.js +89 -20
  4. package/dist/__tests__/autoCct.test.js.map +1 -1
  5. package/dist/__tests__/autostart.test.js +87 -41
  6. package/dist/__tests__/autostart.test.js.map +1 -1
  7. package/dist/__tests__/cctUtil.test.js +26 -27
  8. package/dist/__tests__/cctUtil.test.js.map +1 -1
  9. package/dist/__tests__/cli.smoke.test.js +18 -13
  10. package/dist/__tests__/cli.smoke.test.js.map +1 -1
  11. package/dist/__tests__/intensityApi.test.js +4 -9
  12. package/dist/__tests__/intensityApi.test.js.map +1 -1
  13. package/dist/__tests__/lightControl.test.js +79 -68
  14. package/dist/__tests__/lightControl.test.js.map +1 -1
  15. package/dist/__tests__/setupTests.js +9 -8
  16. package/dist/__tests__/setupTests.js.map +1 -1
  17. package/dist/__tests__/simulateSchedule.test.d.ts +2 -0
  18. package/dist/__tests__/simulateSchedule.test.d.ts.map +1 -0
  19. package/dist/__tests__/simulateSchedule.test.js +87 -0
  20. package/dist/__tests__/simulateSchedule.test.js.map +1 -0
  21. package/dist/autostart.js +19 -60
  22. package/dist/autostart.js.map +1 -1
  23. package/dist/cctUtil.d.ts.map +1 -1
  24. package/dist/cctUtil.js +16 -21
  25. package/dist/cctUtil.js.map +1 -1
  26. package/dist/cli.d.ts +2 -2
  27. package/dist/cli.d.ts.map +1 -1
  28. package/dist/cli.js +52 -231
  29. package/dist/cli.js.map +1 -1
  30. package/dist/commands/__tests__/integration.test.d.ts +2 -0
  31. package/dist/commands/__tests__/integration.test.d.ts.map +1 -0
  32. package/dist/commands/__tests__/integration.test.js +279 -0
  33. package/dist/commands/__tests__/integration.test.js.map +1 -0
  34. package/dist/commands/autoCct.d.ts +1 -1
  35. package/dist/commands/autoCct.d.ts.map +1 -1
  36. package/dist/commands/autoCct.js +90 -76
  37. package/dist/commands/autoCct.js.map +1 -1
  38. package/dist/commands/cct.d.ts +1 -1
  39. package/dist/commands/cct.d.ts.map +1 -1
  40. package/dist/commands/cct.js +17 -23
  41. package/dist/commands/cct.js.map +1 -1
  42. package/dist/commands/color.d.ts +1 -1
  43. package/dist/commands/color.d.ts.map +1 -1
  44. package/dist/commands/color.js +9 -15
  45. package/dist/commands/color.js.map +1 -1
  46. package/dist/commands/config.d.ts +4 -0
  47. package/dist/commands/config.d.ts.map +1 -0
  48. package/dist/commands/config.js +219 -0
  49. package/dist/commands/config.js.map +1 -0
  50. package/dist/commands/discover.d.ts +1 -1
  51. package/dist/commands/discover.d.ts.map +1 -1
  52. package/dist/commands/discover.js +8 -14
  53. package/dist/commands/discover.js.map +1 -1
  54. package/dist/commands/hsi.d.ts +1 -1
  55. package/dist/commands/hsi.d.ts.map +1 -1
  56. package/dist/commands/hsi.js +11 -17
  57. package/dist/commands/hsi.js.map +1 -1
  58. package/dist/commands/intensity.d.ts +1 -1
  59. package/dist/commands/intensity.d.ts.map +1 -1
  60. package/dist/commands/intensity.js +9 -15
  61. package/dist/commands/intensity.js.map +1 -1
  62. package/dist/commands/list.d.ts +1 -1
  63. package/dist/commands/list.d.ts.map +1 -1
  64. package/dist/commands/list.js +6 -12
  65. package/dist/commands/list.js.map +1 -1
  66. package/dist/commands/power.d.ts +1 -1
  67. package/dist/commands/power.d.ts.map +1 -1
  68. package/dist/commands/power.js +18 -24
  69. package/dist/commands/power.js.map +1 -1
  70. package/dist/commands/printSchedule.d.ts +5 -0
  71. package/dist/commands/printSchedule.d.ts.map +1 -0
  72. package/dist/commands/{schedule.js → printSchedule.js} +92 -84
  73. package/dist/commands/printSchedule.js.map +1 -0
  74. package/dist/commands/service.d.ts +1 -1
  75. package/dist/commands/service.d.ts.map +1 -1
  76. package/dist/commands/service.js +54 -88
  77. package/dist/commands/service.js.map +1 -1
  78. package/dist/commands/simulateSchedule.d.ts +1 -1
  79. package/dist/commands/simulateSchedule.d.ts.map +1 -1
  80. package/dist/commands/simulateSchedule.js +50 -70
  81. package/dist/commands/simulateSchedule.js.map +1 -1
  82. package/dist/commands/status.d.ts +1 -1
  83. package/dist/commands/status.d.ts.map +1 -1
  84. package/dist/commands/status.js +8 -14
  85. package/dist/commands/status.js.map +1 -1
  86. package/dist/commands.d.ts +1 -1
  87. package/dist/commands.d.ts.map +1 -1
  88. package/dist/commands.js +56 -33
  89. package/dist/commands.js.map +1 -1
  90. package/dist/constants.d.ts +13 -14
  91. package/dist/constants.d.ts.map +1 -1
  92. package/dist/constants.js +21 -27
  93. package/dist/constants.js.map +1 -1
  94. package/dist/discovery.js +8 -15
  95. package/dist/discovery.js.map +1 -1
  96. package/dist/geoipUtil.js +3 -9
  97. package/dist/geoipUtil.js.map +1 -1
  98. package/dist/lightControl.js +18 -20
  99. package/dist/lightControl.js.map +1 -1
  100. package/dist/test/MockLightServer.d.ts +13 -0
  101. package/dist/test/MockLightServer.d.ts.map +1 -0
  102. package/dist/test/MockLightServer.js +140 -0
  103. package/dist/test/MockLightServer.js.map +1 -0
  104. package/dist/types.d.ts +4 -1
  105. package/dist/types.d.ts.map +1 -1
  106. package/dist/types.js +1 -2
  107. package/package.json +16 -15
  108. package/scripts/release.js +112 -0
  109. package/scripts/test.sh +2 -5
  110. package/dist/commands/schedule.d.ts +0 -5
  111. package/dist/commands/schedule.d.ts.map +0 -1
  112. package/dist/commands/schedule.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,12 +1,51 @@
1
- # Changelog
1
+ ## [1.3.6] - 2025-12-14
2
2
 
3
- All notable changes to this project will be documented in this file.
3
+ - **Fix**: Updated workflow to use latest `npm` version for better OIDC support.
4
4
 
5
- ## [1.1.2] - 2024-11-01
5
+ ## [1.3.5] - 2025-12-14
6
+
7
+ - **Fix**: Re-applied `registry-url` configuration fix (previous attempt in v1.3.4 failed to update workflow).
8
+
9
+ ## [1.3.4] - 2025-12-14
10
+
11
+ - **Fix**: Restored `registry-url` configuration (required for OIDC `ENEEDAUTH` fix).
12
+
13
+ ## [1.3.3] - 2025-12-14
14
+
15
+ - **Fix**: Removed conflicting `registry-url` configuration to enable OIDC authentication.
16
+
17
+ ## [1.3.2] - 2025-12-14
18
+
19
+ - **Fix**: Updated release workflow to use NPM Trusted Publishing (OIDC) instead of auth tokens.
20
+
21
+ ## [1.3.1] - 2025-12-14
22
+
23
+ - **Fix**: Resolved timezone issue in integration tests causing CI failures.
24
+
25
+ ## [1.3.0] - 2025-12-14
26
+
27
+ - **Breaking**: Migrated project to ESM (`type: module`).
28
+ - **Breaking**: Migrated testing framework from Jest to Vitest.
29
+ - **Feature**: Added `intensityMultiplier` support to `auto-cct`.
30
+ - **Feature**: `auto-cct` command now accepts a device argument (defaults to 'all').
31
+ - **Refactor**: Renamed `schedule` command to `print-schedule`.
32
+ - **Fix**: Resolved `suncalc` import issues.
33
+ - **Fix**: Improved CLI output styling for light mode terminals.
34
+ - **Chore**: Comprehensive linting and formatting fixes.
35
+
36
+ ## [1.1.4] - 2025-11-02
37
+
38
+ - test token config
39
+
40
+ ## [1.1.3] - 2025-11-02
41
+
42
+ - curve config and refactors
43
+
44
+ ## [1.1.2] - 2025-11-01
6
45
 
7
46
  - Enhanced CLI help output and documentation
8
47
 
9
- ## [1.1.0] - 2024-10-31
48
+ ## [1.1.0] - 2025-10-31
10
49
 
11
50
  - Added more curves for auto-cct
12
51
  - Improved schedule table display with all curves
@@ -16,7 +55,7 @@ All notable changes to this project will be documented in this file.
16
55
  - Added more special times in schedule (e.g., Nautical Dawn)
17
56
  - Various tests and refactoring
18
57
 
19
- ## [1.0.3] - 2024-10-30
58
+ ## [1.0.3] - 2025-10-30
20
59
 
21
60
  - Initial stable release with full CLI functionality
22
61
  - WebSocket control for Aputure Amaran lights
package/README.md CHANGED
@@ -10,14 +10,19 @@ Written with AI mostly, including this documentation. Thanks to [Zac for his co
10
10
 
11
11
  1. Clone this repository or download the files
12
12
  2. Install dependencies:
13
+
13
14
  ```bash
14
15
  npm install
15
16
  ```
17
+
16
18
  3. Build the project:
19
+
17
20
  ```bash
18
21
  npm run build
19
22
  ```
23
+
20
24
  4. Optionally, install globally:
25
+
21
26
  ```bash
22
27
  npm install -g .
23
28
  ```
@@ -64,9 +69,17 @@ amaran-cli discover -d
64
69
 
65
70
  This command uses `lsof` to find the WebSocket port that the Amaran Desktop application is listening on, then saves it to your configuration file for future use.
66
71
 
72
+ ## Device Identification
73
+
74
+ Devices can be identified by:
75
+
76
+ - **Device name**: Case-insensitive partial matching (e.g., "key" matches "Key Light")
77
+ - **Node ID**: Exact match of the device's node_id
78
+
67
79
  ## Usage
68
80
 
69
81
  ### List all available lights
82
+
70
83
  ```bash
71
84
  amaran-cli list
72
85
  # or
@@ -74,6 +87,7 @@ amaran-cli ls
74
87
  ```
75
88
 
76
89
  ### Control lights
90
+
77
91
  ```bash
78
92
  # Turn light on
79
93
  amaran-cli on "Light Name"
@@ -96,6 +110,7 @@ amaran-cli toggle
96
110
  ```
97
111
 
98
112
  ### Set light properties
113
+
99
114
  ```bash
100
115
  # Set intensity (0-100%)
101
116
  amaran-cli intensity 75 "Light Name"
@@ -135,6 +150,7 @@ amaran-cli color blue -i 50
135
150
  **Note:** For all commands that support device names, you can omit the device name or use `all` to apply the command to all lights. Commands are throttled with 250ms delay between each device to prevent overwhelming the server.
136
151
 
137
152
  ### Auto CCT (Circadian Lighting)
153
+
138
154
  ```bash
139
155
  # Set CCT for all lights based on current time and location (auto-detected via geoip)
140
156
  amaran-cli auto-cct
@@ -156,18 +172,21 @@ amaran-cli auto-cct -d
156
172
  ```
157
173
 
158
174
  The `auto-cct` command automatically adjusts color temperature based on sunrise/sunset times for your location. By default, it maps the circadian curve to:
175
+
159
176
  - **Before sunrise / After sunset**: 2000K at 5% intensity (warm, dim night lighting)
160
177
  - **Solar noon**: 6500K at 100% intensity (cool, bright daylight)
161
178
  - **Between sunrise and sunset**: Smooth bell curve transition from 2000K/5% → 6500K/100% → 2000K/5%
162
179
 
163
180
  This mimics natural daylight changes throughout the day for more comfortable, circadian-friendly lighting. Both color temperature and brightness follow the same curve, providing natural dimming at dawn/dusk.
164
181
 
165
- **Location Priority:**
182
+ #### Location Priority
183
+
166
184
  1. Command-line `--lat` and `--lon` arguments (highest priority)
167
185
  2. Config file defaults (set with `amaran-cli config --lat <lat> --lon <lon>`)
168
186
  3. GeoIP lookup based on public IP address (fallback)
169
187
 
170
- **Bounds (optional):**
188
+ #### Bounds (optional)
189
+
171
190
  You can constrain the auto-cct curve to your preferred ranges via config:
172
191
 
173
192
  ```bash
@@ -180,6 +199,7 @@ amaran-cli config --intensity-min 10 --intensity-max 80
180
199
  # Show the saved configuration
181
200
  amaran-cli config --show
182
201
  ```
202
+
183
203
  If a bound is not set, the default is used. When both min and max are set, min must be <= max.
184
204
 
185
205
  ### Running Auto-CCT as a Circadian Lighting Service
@@ -218,22 +238,25 @@ amaran-cli circadian-service start
218
238
  amaran-cli circadian-service uninstall
219
239
  ```
220
240
 
221
- **Backward Compatibility:**
241
+ #### Backward Compatibility
242
+
222
243
  The `service` command is still available as an alias to `circadian-service`:
244
+
223
245
  ```bash
224
246
  # These commands work the same way
225
247
  amaran-cli service install
226
248
  amaran-cli circadian-service install
227
249
  ```
228
250
 
229
- **Installation Detection:**
251
+ #### Installation Detection
252
+
230
253
  - The service automatically detects if amaran-cli is installed globally (via `npm install -g`) or running from a local development build
231
254
  - Global installations run the executable directly for better performance
232
255
  - Local development builds use Node.js to run the built JavaScript files
233
256
 
234
257
  The service uses macOS launchd and will automatically start on login. Logs are stored in `~/Library/Logs/amaran-circadian-service.log`.
235
258
 
236
- **Alternative: Using Cron**
259
+ #### Alternative: Using Cron
237
260
 
238
261
  If you prefer using cron instead of launchd, the included script handles both global and local installations:
239
262
 
@@ -250,7 +273,7 @@ crontab -e
250
273
  tail -f ~/.amaran-circadian-service.log
251
274
  ```
252
275
 
253
- **Manual launchd Setup:**
276
+ #### Manual launchd Setup
254
277
 
255
278
  For advanced users who want to create the service manually:
256
279
 
@@ -265,87 +288,86 @@ View how color temperature and intensity will change throughout the day:
265
288
 
266
289
  ```console
267
290
  # Preview schedule for today at your current location
268
- $ amaran-cli schedule
291
+ $ amaran-cli print-schedule
269
292
 
270
293
  ═══════════════════════════════════════════════════════════
271
294
  Auto-CCT Schedule Preview
272
295
  ═══════════════════════════════════════════════════════════
273
296
 
274
- Location: 37.7852°, -122.3874° (geoip (136.24.146.157))
275
- Date: Saturday, November 1, 2025
297
+ Location: 38.XXXX°, -122.XXXX° (geoip (XXX.XXX.XXX.157))
298
+ Date: Sunday, November 2, 2025
276
299
  Interval: Every 30 minutes
277
300
  Curve: All available curves
278
301
 
279
- NE Night End : 06:07 AM GH Golden Hour : 05:35 PM
280
- DN Nautical Dawn : 06:38 AM SB Sunset Start : 06:09 PM
281
- DA Dawn : 07:09 AM SS Sunset : 06:12 PM
282
- SR Sunrise : 07:36 AM ND Nautical Dusk : 07:10 PM
283
- SE Sunrise End : 07:39 AM DU Dusk : 06:39 PM
284
- GE Golden Hour End : 08:13 AM NI Night : 07:41 PM
285
- SN Solar Noon : 12:54 PM NA Nadir : 12:54 AM
302
+ NE Night End : 05:08 AM GH Golden Hour : 04:34 PM
303
+ DN Nautical Dawn : 05:39 AM SB Sunset Start : 05:08 PM
304
+ DA Dawn : 06:10 AM SS Sunset : 05:11 PM
305
+ SR Sunrise : 06:37 AM ND Nautical Dusk : 06:09 PM
306
+ SE Sunrise End : 06:40 AM DU Dusk : 05:38 PM
307
+ GE Golden Hour End : 07:14 AM NI Night : 06:40 PM
308
+ SN Solar Noon : 11:54 AM NA Nadir : 12:54 AM
286
309
 
287
310
 
288
311
  ─────────────────────────────────────────────────────────────────────────────────────────────────
289
- Time HANN WM_SMALL WM_MEDIUM WM_LARGE CIE SUN_ALT PEREZ
312
+ Time HANN WM_SMALL WM_MEDIUM WM_LARGE CIE SUN_ALT PEREZ
290
313
  ─────────────────────────────────────────────────────────────────────────────────────────────────
291
- 05:37 AM 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5%
292
- 06:07 AM NE 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5%
293
- 06:37 AM 1751K/6% 2326K/21% 2785K/32% 3780K/57% 1700K/5% 1700K/5% 1700K/5%
294
- 06:38 AM DN 1753K/6% 2339K/21% 2807K/33% 3817K/58% 1700K/5% 1700K/5% 1700K/5%
295
- 07:07 AM 1900K/10% 2935K/36% 3780K/57% 5182K/92% 1700K/5% 1700K/5% 1700K/5%
296
- 07:09 AM DA 1911K/10% 2967K/37% 3829K/58% 5227K/93% 3225K/5% 2867K/5% 3031K/5%
297
- 07:36 AM SR 2130K/16% 3488K/50% 4573K/77% 5500K/100% 3865K/7% 3521K/9% 3793K/6%
298
- 07:37 AM 2141K/16% 3510K/50% 4602K/78% 5500K/100% 3906K/7% 3550K/9% 3859K/6%
299
- 07:39 AM SE 2156K/16% 3540K/51% 4640K/79% 5500K/100% 3963K/8% 3589K/10% 3952K/6%
300
- 08:07 AM 2459K/24% 4036K/63% 5182K/92% 5500K/100% 3785K/9% 3796K/17% 3883K/13%
301
- 08:13 AM GE 2528K/26% 4130K/66% 5261K/94% 5500K/100% 3750K/9% 3836K/19% 3879K/15%
302
- 08:37 AM 2839K/34% 4498K/75% 5471K/99% 5500K/100% 3641K/9% 3999K/25% 3911K/21%
303
- 09:07 AM 3259K/44% 4883K/85% 5500K/100% 5500K/100% 3631K/33% 4193K/35% 4174K/26%
304
- 09:37 AM 3697K/55% 5182K/92% 5500K/100% 5500K/100% 3874K/66% 4375K/44% 4605K/46%
305
- 10:07 AM 4130K/66% 5385K/97% 5500K/100% 5500K/100% 4097K/87% 4543K/52% 4986K/79%
306
- 10:37 AM 4535K/76% 5487K/100% 5500K/100% 5500K/100% 4296K/97% 4692K/60% 4664K/97%
307
- 11:07 AM 4890K/85% 5500K/100% 5500K/100% 5500K/100% 4465K/100% 4793K/100% 4765K/100%
308
- 11:37 AM 5176K/92% 5500K/100% 5500K/100% 5500K/100% 4599K/100% 4860K/100% 4845K/100%
309
- 12:07 PM 5378K/97% 5500K/100% 5500K/100% 5500K/100% 4693K/100% 4906K/100% 4902K/100%
310
- 12:37 PM 5484K/100% 5500K/100% 5500K/100% 5500K/100% 4741K/100% 4931K/100% 4931K/100%
311
- 12:54 PM SN 5500K/100% 5500K/100% 5500K/100% 5500K/100% 4748K/100% 4934K/100% 4935K/100%
312
- 01:07 PM 5490K/100% 5500K/100% 5500K/100% 5500K/100% 4742K/100% 4931K/100% 4931K/100%
313
- 01:37 PM 5395K/97% 5500K/100% 5500K/100% 5500K/100% 4696K/100% 4908K/100% 4903K/100%
314
- 02:07 PM 5204K/93% 5500K/100% 5500K/100% 5500K/100% 4604K/100% 4862K/100% 4848K/100%
315
- 02:37 PM 4927K/86% 5500K/100% 5500K/100% 5500K/100% 4472K/100% 4796K/100% 4769K/100%
316
- 03:07 PM 4579K/77% 5493K/100% 5500K/100% 5500K/100% 4304K/97% 4698K/60% 4668K/97%
317
- 03:37 PM 4179K/67% 5402K/98% 5500K/100% 5500K/100% 4106K/87% 4550K/53% 5000K/80%
318
- 04:07 PM 3748K/56% 5210K/93% 5500K/100% 5500K/100% 3884K/67% 4383K/44% 4624K/48%
319
- 04:37 PM 3309K/45% 4923K/86% 5500K/100% 5500K/100% 3642K/34% 4201K/35% 4191K/26%
320
- 05:07 PM 2886K/35% 4547K/76% 5485K/100% 5500K/100% 3637K/9% 4008K/25% 3917K/21%
321
- 05:35 PM GH 2528K/26% 4130K/66% 5261K/94% 5500K/100% 3763K/9% 3820K/18% 3881K/14%
322
- 05:37 PM 2501K/25% 4093K/65% 5231K/93% 5500K/100% 3777K/9% 3805K/17% 3882K/14%
323
- 06:07 PM 2174K/17% 3574K/52% 4683K/80% 5500K/100% 3950K/8% 3580K/10% 3930K/6%
324
- 06:09 PM SB 2156K/16% 3540K/51% 4640K/79% 5500K/100% 3886K/7% 3536K/9% 3826K/6%
325
- 06:12 PM SS 2130K/16% 3488K/50% 4573K/77% 5500K/100% 3791K/7% 3468K/8% 3679K/6%
326
- 06:37 PM 1924K/11% 3004K/38% 3886K/60% 5276K/94% 3223K/5% 2859K/5% 3031K/5%
327
- 06:39 PM DU 1911K/10% 2967K/37% 3829K/58% 5227K/93% 1700K/5% 1700K/5% 1700K/5%
328
- 07:07 PM 1763K/7% 2398K/22% 2907K/35% 3989K/62% 1700K/5% 1700K/5% 1700K/5%
329
- 07:10 PM ND 1753K/6% 2339K/21% 2807K/33% 3817K/58% 1700K/5% 1700K/5% 1700K/5%
330
- 07:37 PM 1701K/5% 1773K/7% 1828K/8% 1955K/11% 1700K/5% 1700K/5% 1700K/5%
331
- 07:41 PM NI 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5%
332
- 08:07 PM 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5%
314
+ 04:38 AM 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5%
315
+ 05:08 AM NE 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5%
316
+ 05:38 AM 1764K/6% 2493K/21% 3074K/32% 4333K/57% 1700K/5% 1700K/5% 1700K/5%
317
+ 05:39 AM DN 1767K/6% 2509K/21% 3102K/33% 4382K/58% 1700K/5% 1700K/5% 1700K/5%
318
+ 06:08 AM 1954K/10% 3264K/36% 4333K/57% 6103K/92% 1700K/5% 1700K/5% 1700K/5%
319
+ 06:10 AM DA 1968K/10% 3305K/37% 4398K/58% 6163K/93% 3627K/5% 3175K/5% 3382K/5%
320
+ 06:37 AM SR 2247K/16% 3966K/50% 5339K/77% 6500K/100% 4435K/7% 4001K/9% 4345K/6%
321
+ 06:38 AM 2259K/16% 3991K/50% 5372K/78% 6500K/100% 4482K/7% 4033K/9% 4419K/6%
322
+ 06:40 AM SE 2281K/17% 4032K/51% 5424K/79% 6500K/100% 4559K/8% 4086K/10% 4545K/6%
323
+ 07:08 AM 2663K/24% 4656K/64% 6103K/92% 6500K/100% 4335K/9% 4346K/17% 4457K/13%
324
+ 07:14 AM GE 2754K/26% 4781K/66% 6207K/94% 6500K/100% 4290K/9% 4398K/19% 4453K/15%
325
+ 07:38 AM 3144K/34% 5240K/75% 6466K/99% 6500K/100% 4153K/9% 4602K/25% 4492K/21%
326
+ 08:08 AM 3677K/44% 5727K/85% 6500K/100% 6500K/100% 4134K/33% 4846K/35% 4818K/26%
327
+ 08:38 AM 4232K/55% 6103K/92% 6500K/100% 6500K/100% 4440K/66% 5075K/44% 5358K/45%
328
+ 09:08 AM 4780K/66% 6358K/97% 6500K/100% 6500K/100% 4720K/87% 5285K/52% 5838K/79%
329
+ 09:38 AM 5291K/76% 6485K/100% 6500K/100% 6500K/100% 4969K/97% 5472K/59% 5437K/97%
330
+ 10:08 AM 5739K/85% 6500K/100% 6500K/100% 6500K/100% 5180K/100% 5600K/100% 5564K/100%
331
+ 10:38 AM 6098K/92% 6500K/100% 6500K/100% 6500K/100% 5347K/100% 5684K/100% 5664K/100%
332
+ 11:08 AM 6351K/97% 6500K/100% 6500K/100% 6500K/100% 5463K/100% 5742K/100% 5734K/100%
333
+ 11:38 AM 6482K/100% 6500K/100% 6500K/100% 6500K/100% 5522K/100% 5771K/100% 5769K/100%
334
+ 11:54 AM SN 6500K/100% 6500K/100% 6500K/100% 6500K/100% 5529K/100% 5775K/100% 5774K/100%
335
+ 12:08 PM 6486K/100% 6500K/100% 6500K/100% 6500K/100% 5522K/100% 5771K/100% 5769K/100%
336
+ 12:38 PM 6361K/97% 6500K/100% 6500K/100% 6500K/100% 5461K/100% 5741K/100% 5733K/100%
337
+ 01:08 PM 6115K/92% 6500K/100% 6500K/100% 6500K/100% 5344K/100% 5682K/100% 5663K/100%
338
+ 01:38 PM 5761K/85% 6500K/100% 6500K/100% 6500K/100% 5177K/100% 5598K/100% 5562K/100%
339
+ 02:08 PM 5317K/77% 6489K/100% 6500K/100% 6500K/100% 4964K/97% 5468K/59% 5434K/97%
340
+ 02:38 PM 4808K/67% 6368K/97% 6500K/100% 6500K/100% 4714K/87% 5281K/52% 5830K/79%
341
+ 03:08 PM 4262K/56% 6120K/93% 6500K/100% 6500K/100% 4434K/66% 5070K/43% 5347K/45%
342
+ 03:38 PM 3706K/45% 5750K/85% 6500K/100% 6500K/100% 4128K/32% 4841K/34% 4809K/25%
343
+ 04:08 PM 3172K/34% 5269K/76% 6474K/100% 6500K/100% 4156K/9% 4597K/25% 4489K/21%
344
+ 04:34 PM GH 2754K/26% 4781K/66% 6207K/94% 6500K/100% 4306K/9% 4378K/18% 4454K/14%
345
+ 04:38 PM 2687K/25% 4690K/64% 6132K/93% 6500K/100% 4340K/9% 4340K/17% 4458K/13%
346
+ 05:08 PM SB 2281K/17% 4032K/51% 5424K/79% 6500K/100% 4461K/7% 4019K/9% 4385K/6%
347
+ 05:11 PM SS 2247K/16% 3966K/50% 5339K/77% 6500K/100% 4341K/7% 3933K/8% 4199K/6%
348
+ 05:38 PM DU 1968K/10% 3305K/37% 4398K/58% 6163K/93% 1700K/5% 1700K/5% 1700K/5%
349
+ 06:08 PM 1772K/6% 2535K/22% 3145K/34% 4457K/60% 1700K/5% 1700K/5% 1700K/5%
350
+ 06:09 PM ND 1767K/6% 2509K/21% 3102K/33% 4382K/58% 1700K/5% 1700K/5% 1700K/5%
351
+ 06:38 PM 1700K/5% 1743K/6% 1775K/7% 1849K/8% 1700K/5% 1700K/5% 1700K/5%
352
+ 06:40 PM NI 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5%
353
+ 07:08 PM 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5% 1700K/5%
333
354
  ─────────────────────────────────────────────────────────────────────────────────────────────────
334
355
 
335
356
  # Preview with manual location
336
- amaran-cli schedule --lat 40.7128 --lon -74.0060
357
+ amaran-cli print-schedule --lat 40.7128 --lon -74.0060
337
358
 
338
359
  # Preview for a specific date
339
- amaran-cli schedule --date 2025-12-21
360
+ amaran-cli print-schedule --date 2025-12-21
340
361
 
341
362
  # Change time interval (default: 30 minutes)
342
- amaran-cli schedule --interval 15
363
+ amaran-cli print-schedule --interval 15
343
364
 
344
365
  # Combine options
345
- amaran-cli schedule --lat 51.5074 --lon -0.1278 --date 2025-06-21 --interval 60
366
+ amaran-cli print-schedule --lat 51.5074 --lon -0.1278 --date 2025-06-21 --interval 60
346
367
  ```
347
368
 
348
369
  The schedule shows CCT and intensity values from 30 minutes before sunrise to 30 minutes after sunset, with special highlighting for:
370
+
349
371
  - **Sunrise** (yellow)
350
372
  - **Solar Noon** (green, bold)
351
373
  - **Sunset** (magenta)
@@ -355,22 +377,26 @@ This helps you visualize and plan your automated lighting schedule before implem
355
377
  Note: The schedule respects any configured bounds set via `amaran-cli config --cct-min/--cct-max` and `--intensity-min/--intensity-max`. If no bounds are set, it uses the default curve from `calculateCCT`.
356
378
 
357
379
  ### Get light status
380
+
358
381
  ```bash
359
382
  amaran-cli status "Light Name"
360
383
  ```
361
384
 
362
385
  ### Global options
386
+
363
387
  All commands support these options:
388
+
364
389
  - `-u, --url <url>`: Override WebSocket URL
365
390
  - `-c, --client-id <id>`: Override client ID
366
391
  - `-d, --debug`: Enable debug mode
367
392
 
368
393
  Example:
394
+
369
395
  ```bash
370
396
  amaran-cli list -u ws://192.168.1.100:60124 -d
371
397
  ```
372
398
 
373
- ## Examples
399
+ ## Usage Examples
374
400
 
375
401
  ```bash
376
402
  # Configure for remote Amaran Desktop
@@ -409,6 +435,10 @@ amaran-cli off
409
435
 
410
436
  ## Development
411
437
 
438
+ The localhost amaran desktop websocket API looks like to be near identical or identical to the Open API Sidus has published at <https://tools.sidus.link/openapi/docs/usage> . So if `lightControl.ts` is missing any functionality you can probably use the OpenAPI spec to implement the new functionality fairly quickly. This cli would probably work with the Sidus desktop apps as well, as well as Windows verisons of the Amaran desktop app but I haven't tested it. If you want to submit PRs for it, feel free!
439
+
440
+ Extending command line tool to work with their networked Open API would probably be fairly simple to do since the local Websocket API is very similar to the Open API.
441
+
412
442
  ```bash
413
443
  # Run in development mode
414
444
  npm run dev
@@ -419,9 +449,3 @@ npm run build
419
449
  # Clean build artifacts
420
450
  npm run clean
421
451
  ```
422
-
423
- ## Device Identification
424
-
425
- Devices can be identified by:
426
- - **Device name**: Case-insensitive partial matching (e.g., "key" matches "Key Light")
427
- - **Node ID**: Exact match of the device's node_id
@@ -1,17 +1,12 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const globals_1 = require("@jest/globals");
7
- const commander_1 = require("commander");
8
- const commands_1 = __importDefault(require("../commands"));
9
- globals_1.jest.mock('../geoipUtil', () => ({
10
- getLocationFromIP: globals_1.jest.fn(() => ({ ll: [37.7749, -122.4194] })),
1
+ import { Command } from 'commander';
2
+ import { vi } from 'vitest';
3
+ import registerCommands from '../commands.js';
4
+ vi.mock('../geoipUtil', () => ({
5
+ getLocationFromIP: vi.fn(() => ({ ll: [37.7749, -122.4194] })),
11
6
  }));
12
- globals_1.jest.mock('../cctUtil', () => ({
13
- calculateCCT: globals_1.jest.fn(() => ({ cct: 5600, intensity: 500 })),
14
- parseCurveType: globals_1.jest.fn(() => 'HANN'),
7
+ vi.mock('../cctUtil', () => ({
8
+ calculateCCT: vi.fn(() => ({ cct: 5600, intensity: 500 })),
9
+ parseCurveType: vi.fn(() => 'HANN'),
15
10
  CurveType: {
16
11
  HANN: 'hann',
17
12
  WIDER_MIDDLE_SMALL: 'wider-middle-small',
@@ -24,7 +19,7 @@ globals_1.jest.mock('../cctUtil', () => ({
24
19
  }));
25
20
  describe('auto-cct command', () => {
26
21
  const originalFetch = global.fetch;
27
- const mockFetch = globals_1.jest.fn();
22
+ const mockFetch = vi.fn();
28
23
  beforeAll(() => {
29
24
  mockFetch.mockImplementation(async () => ({
30
25
  json: async () => ({ ip: '1.2.3.4' }),
@@ -38,18 +33,18 @@ describe('auto-cct command', () => {
38
33
  global.fetch = originalFetch;
39
34
  });
40
35
  test('skips sleeping lights when running auto-cct', async () => {
41
- const setCCT = globals_1.jest.fn();
42
- const disconnect = globals_1.jest.fn(async () => Promise.resolve());
36
+ const setCCT = vi.fn();
37
+ const disconnect = vi.fn(async () => Promise.resolve());
43
38
  const sleepState = {
44
39
  '400J5-F2C008': false,
45
40
  '400J5-F2C009': true,
46
41
  };
47
42
  const controllerStub = {
48
- getDevices: globals_1.jest.fn(() => [
43
+ getDevices: vi.fn(() => [
49
44
  { node_id: '400J5-F2C008', device_name: 'On Light' },
50
45
  { node_id: '400J5-F2C009', device_name: 'Off Light' },
51
46
  ]),
52
- getLightSleepStatus: globals_1.jest.fn((nodeId, cb) => {
47
+ getLightSleepStatus: vi.fn((nodeId, cb) => {
53
48
  setImmediate(() => cb(true, 'ok', { sleep: sleepState[nodeId] }));
54
49
  }),
55
50
  setCCT,
@@ -62,14 +57,88 @@ describe('auto-cct command', () => {
62
57
  loadConfig: () => ({}),
63
58
  saveWsUrl: undefined,
64
59
  };
65
- const program = new commander_1.Command();
60
+ const program = new Command();
66
61
  program.exitOverride();
67
- (0, commands_1.default)(program, deps);
62
+ registerCommands(program, deps);
68
63
  await program.parseAsync(['node', 'test', 'auto-cct']);
69
64
  expect(setCCT).toHaveBeenCalledTimes(1);
70
65
  // auto-cct should pass through calculateCCT result
71
66
  expect(setCCT).toHaveBeenCalledWith('400J5-F2C008', 5600, 500);
72
67
  expect(disconnect).toHaveBeenCalledTimes(1);
73
68
  });
69
+ test('applies intensity multiplier from config', async () => {
70
+ const setCCT = vi.fn();
71
+ const disconnect = vi.fn(async () => Promise.resolve());
72
+ const controllerStub = {
73
+ getDevices: vi.fn(() => [
74
+ { node_id: '400J5-F2C008', device_name: 'Key Light' },
75
+ { node_id: '400J5-F2C009', device_name: 'Fill Light' },
76
+ ]),
77
+ getLightSleepStatus: vi.fn((_nodeId, cb) => {
78
+ setImmediate(() => cb(true, 'ok', { sleep: false }));
79
+ }),
80
+ setCCT,
81
+ disconnect,
82
+ };
83
+ const deps = {
84
+ createController: async () => controllerStub,
85
+ findDevice: (_controller, _deviceQuery) => null,
86
+ asyncCommand: (fn) => (...args) => fn(...args),
87
+ loadConfig: () => ({
88
+ intensityMultiplier: {
89
+ '400J5-F2C008': 0.5, // 50% multiplier
90
+ // 400J5-F2C009 has no multiplier, defaults to 1.0
91
+ },
92
+ }),
93
+ saveWsUrl: undefined,
94
+ };
95
+ const program = new Command();
96
+ program.exitOverride();
97
+ registerCommands(program, deps);
98
+ await program.parseAsync(['node', 'test', 'auto-cct']);
99
+ expect(setCCT).toHaveBeenCalledTimes(2);
100
+ // 5600K at 50% intensity (base 500 * 0.5 = 250)
101
+ // Note: The logic in autoCct computes percent first, then multiplies.
102
+ // Base intensity 500 -> 50%. 50% * 0.5 = 25%.
103
+ // Then it converts back to raw intensity: 500 * (25 / 50) = 250.
104
+ expect(setCCT).toHaveBeenCalledWith('400J5-F2C008', 5600, 250);
105
+ // Normal intensity for the other light
106
+ expect(setCCT).toHaveBeenCalledWith('400J5-F2C009', 5600, 500);
107
+ expect(disconnect).toHaveBeenCalledTimes(1);
108
+ });
109
+ test('targets specific device when argument is provided', async () => {
110
+ const setCCT = vi.fn();
111
+ const disconnect = vi.fn(async () => Promise.resolve());
112
+ const targetDevice = { node_id: '400J5-F2C008', device_name: 'Target Light' };
113
+ const otherDevice = { node_id: '400J5-F2C009', device_name: 'Other Light' };
114
+ const controllerStub = {
115
+ getDevices: vi.fn(() => [targetDevice, otherDevice]),
116
+ getLightSleepStatus: vi.fn((_nodeId, cb) => {
117
+ setImmediate(() => cb(true, 'ok', { sleep: false }));
118
+ }),
119
+ setCCT,
120
+ disconnect,
121
+ };
122
+ const findDeviceMock = vi.fn((_controller, query) => {
123
+ if (query === 'Target')
124
+ return targetDevice;
125
+ return null;
126
+ });
127
+ const deps = {
128
+ createController: async () => controllerStub,
129
+ findDevice: findDeviceMock,
130
+ asyncCommand: (fn) => (...args) => fn(...args),
131
+ loadConfig: () => ({}),
132
+ saveWsUrl: undefined,
133
+ };
134
+ const program = new Command();
135
+ program.exitOverride();
136
+ registerCommands(program, deps);
137
+ await program.parseAsync(['node', 'test', 'auto-cct', 'Target']);
138
+ expect(findDeviceMock).toHaveBeenCalledWith(controllerStub, 'Target');
139
+ expect(setCCT).toHaveBeenCalledTimes(1);
140
+ expect(setCCT).toHaveBeenCalledWith('400J5-F2C008', 5600, 500);
141
+ expect(disconnect).toHaveBeenCalledTimes(1);
142
+ });
74
143
  });
75
144
  //# sourceMappingURL=autoCct.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"autoCct.test.js","sourceRoot":"","sources":["../../src/__tests__/autoCct.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"autoCct.test.js","sourceRoot":"","sources":["../../src/__tests__/autoCct.test.ts"],"names":[],"mappings":"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"}