amaran-light-cli 1.11.0 → 1.12.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.
- package/README.md +108 -14
- package/dist/__tests__/autoCct.test.js +27 -0
- package/dist/__tests__/autoCct.test.js.map +1 -1
- package/dist/__tests__/bleHttpControl.test.d.ts +2 -0
- package/dist/__tests__/bleHttpControl.test.d.ts.map +1 -0
- package/dist/__tests__/bleHttpControl.test.js +230 -0
- package/dist/__tests__/bleHttpControl.test.js.map +1 -0
- package/dist/__tests__/bleStack.test.d.ts +2 -0
- package/dist/__tests__/bleStack.test.d.ts.map +1 -0
- package/dist/__tests__/bleStack.test.js +1239 -0
- package/dist/__tests__/bleStack.test.js.map +1 -0
- package/dist/__tests__/cctUtil.test.js +9 -4
- package/dist/__tests__/cctUtil.test.js.map +1 -1
- package/dist/__tests__/circadianDashboardSettings.test.d.ts +2 -0
- package/dist/__tests__/circadianDashboardSettings.test.d.ts.map +1 -0
- package/dist/__tests__/circadianDashboardSettings.test.js +82 -0
- package/dist/__tests__/circadianDashboardSettings.test.js.map +1 -0
- package/dist/__tests__/circadianIsolation.test.d.ts +2 -0
- package/dist/__tests__/circadianIsolation.test.d.ts.map +1 -0
- package/dist/__tests__/circadianIsolation.test.js +30 -0
- package/dist/__tests__/circadianIsolation.test.js.map +1 -0
- package/dist/__tests__/cli.config.test.js +49 -0
- package/dist/__tests__/cli.config.test.js.map +1 -1
- package/dist/__tests__/cli.smoke.test.js +34 -0
- package/dist/__tests__/cli.smoke.test.js.map +1 -1
- package/dist/__tests__/currentCct.test.d.ts +2 -0
- package/dist/__tests__/currentCct.test.d.ts.map +1 -0
- package/dist/__tests__/currentCct.test.js +29 -0
- package/dist/__tests__/currentCct.test.js.map +1 -0
- package/dist/__tests__/dashboard.test.d.ts +2 -0
- package/dist/__tests__/dashboard.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard.test.js +126 -0
- package/dist/__tests__/dashboard.test.js.map +1 -0
- package/dist/__tests__/daylightSimulationParseUtils.test.d.ts +2 -0
- package/dist/__tests__/daylightSimulationParseUtils.test.d.ts.map +1 -0
- package/dist/__tests__/daylightSimulationParseUtils.test.js +16 -0
- package/dist/__tests__/daylightSimulationParseUtils.test.js.map +1 -0
- package/dist/__tests__/desktopImport.test.d.ts +2 -0
- package/dist/__tests__/desktopImport.test.d.ts.map +1 -0
- package/dist/__tests__/desktopImport.test.js +234 -0
- package/dist/__tests__/desktopImport.test.js.map +1 -0
- package/dist/__tests__/lightControl.basic.test.d.ts +2 -0
- package/dist/__tests__/lightControl.basic.test.d.ts.map +1 -0
- package/dist/__tests__/lightControl.basic.test.js +119 -0
- package/dist/__tests__/lightControl.basic.test.js.map +1 -0
- package/dist/__tests__/lightControl.colorEffects.test.d.ts +2 -0
- package/dist/__tests__/lightControl.colorEffects.test.d.ts.map +1 -0
- package/dist/__tests__/lightControl.colorEffects.test.js +170 -0
- package/dist/__tests__/lightControl.colorEffects.test.js.map +1 -0
- package/dist/__tests__/lightControl.management.test.d.ts +2 -0
- package/dist/__tests__/lightControl.management.test.d.ts.map +1 -0
- package/dist/__tests__/lightControl.management.test.js +90 -0
- package/dist/__tests__/lightControl.management.test.js.map +1 -0
- package/dist/__tests__/lightControlTestUtils.d.ts +10 -0
- package/dist/__tests__/lightControlTestUtils.d.ts.map +1 -0
- package/dist/__tests__/lightControlTestUtils.js +57 -0
- package/dist/__tests__/lightControlTestUtils.js.map +1 -0
- package/dist/__tests__/meshConfiguration.test.d.ts +2 -0
- package/dist/__tests__/meshConfiguration.test.d.ts.map +1 -0
- package/dist/__tests__/meshConfiguration.test.js +78 -0
- package/dist/__tests__/meshConfiguration.test.js.map +1 -0
- package/dist/__tests__/nativeGroups.test.d.ts +2 -0
- package/dist/__tests__/nativeGroups.test.d.ts.map +1 -0
- package/dist/__tests__/nativeGroups.test.js +104 -0
- package/dist/__tests__/nativeGroups.test.js.map +1 -0
- package/dist/__tests__/programApi.test.d.ts +2 -0
- package/dist/__tests__/programApi.test.d.ts.map +1 -0
- package/dist/__tests__/programApi.test.js +73 -0
- package/dist/__tests__/programApi.test.js.map +1 -0
- package/dist/__tests__/programs.test.d.ts +2 -0
- package/dist/__tests__/programs.test.d.ts.map +1 -0
- package/dist/__tests__/programs.test.js +176 -0
- package/dist/__tests__/programs.test.js.map +1 -0
- package/dist/__tests__/scheduleMaker.test.d.ts +2 -0
- package/dist/__tests__/scheduleMaker.test.d.ts.map +1 -0
- package/dist/__tests__/scheduleMaker.test.js +25 -0
- package/dist/__tests__/scheduleMaker.test.js.map +1 -0
- package/dist/ble/async.d.ts +2 -0
- package/dist/ble/async.d.ts.map +1 -0
- package/dist/ble/async.js +15 -0
- package/dist/ble/async.js.map +1 -0
- package/dist/ble/colors.d.ts +5 -0
- package/dist/ble/colors.d.ts.map +1 -0
- package/dist/ble/colors.js +44 -0
- package/dist/ble/colors.js.map +1 -0
- package/dist/ble/configuration.d.ts +22 -0
- package/dist/ble/configuration.d.ts.map +1 -0
- package/dist/ble/configuration.js +122 -0
- package/dist/ble/configuration.js.map +1 -0
- package/dist/ble/controller.d.ts +118 -0
- package/dist/ble/controller.d.ts.map +1 -0
- package/dist/ble/controller.js +931 -0
- package/dist/ble/controller.js.map +1 -0
- package/dist/ble/crypto.d.ts +34 -0
- package/dist/ble/crypto.d.ts.map +1 -0
- package/dist/ble/crypto.js +178 -0
- package/dist/ble/crypto.js.map +1 -0
- package/dist/ble/daemon.d.ts +2 -0
- package/dist/ble/daemon.d.ts.map +1 -0
- package/dist/ble/daemon.js +76 -0
- package/dist/ble/daemon.js.map +1 -0
- package/dist/ble/dashboard.d.ts +331 -0
- package/dist/ble/dashboard.d.ts.map +1 -0
- package/dist/ble/dashboard.js +280 -0
- package/dist/ble/dashboard.js.map +1 -0
- package/dist/ble/desktop.d.ts +4 -0
- package/dist/ble/desktop.d.ts.map +1 -0
- package/dist/ble/desktop.js +33 -0
- package/dist/ble/desktop.js.map +1 -0
- package/dist/ble/desktopLibrary.d.ts +12 -0
- package/dist/ble/desktopLibrary.d.ts.map +1 -0
- package/dist/ble/desktopLibrary.js +346 -0
- package/dist/ble/desktopLibrary.js.map +1 -0
- package/dist/ble/effects.d.ts +34 -0
- package/dist/ble/effects.d.ts.map +1 -0
- package/dist/ble/effects.js +138 -0
- package/dist/ble/effects.js.map +1 -0
- package/dist/ble/fan.d.ts +244 -0
- package/dist/ble/fan.d.ts.map +1 -0
- package/dist/ble/fan.js +46 -0
- package/dist/ble/fan.js.map +1 -0
- package/dist/ble/library.d.ts +341 -0
- package/dist/ble/library.d.ts.map +1 -0
- package/dist/ble/library.js +201 -0
- package/dist/ble/library.js.map +1 -0
- package/dist/ble/media.d.ts +133 -0
- package/dist/ble/media.d.ts.map +1 -0
- package/dist/ble/media.js +186 -0
- package/dist/ble/media.js.map +1 -0
- package/dist/ble/nativeGroups.d.ts +22 -0
- package/dist/ble/nativeGroups.d.ts.map +1 -0
- package/dist/ble/nativeGroups.js +114 -0
- package/dist/ble/nativeGroups.js.map +1 -0
- package/dist/ble/packets.d.ts +3 -0
- package/dist/ble/packets.d.ts.map +1 -0
- package/dist/ble/packets.js +15 -0
- package/dist/ble/packets.js.map +1 -0
- package/dist/ble/programs.d.ts +318 -0
- package/dist/ble/programs.d.ts.map +1 -0
- package/dist/ble/programs.js +329 -0
- package/dist/ble/programs.js.map +1 -0
- package/dist/ble/provisioning.d.ts +13 -0
- package/dist/ble/provisioning.d.ts.map +1 -0
- package/dist/ble/provisioning.js +39 -0
- package/dist/ble/provisioning.js.map +1 -0
- package/dist/ble/server.d.ts +18 -0
- package/dist/ble/server.d.ts.map +1 -0
- package/dist/ble/server.js +548 -0
- package/dist/ble/server.js.map +1 -0
- package/dist/ble/service.d.ts +2 -0
- package/dist/ble/service.d.ts.map +1 -0
- package/dist/ble/service.js +77 -0
- package/dist/ble/service.js.map +1 -0
- package/dist/ble/settings.d.ts +18 -0
- package/dist/ble/settings.d.ts.map +1 -0
- package/dist/ble/settings.js +25 -0
- package/dist/ble/settings.js.map +1 -0
- package/dist/ble/setup.d.ts +2 -0
- package/dist/ble/setup.d.ts.map +1 -0
- package/dist/ble/setup.js +31 -0
- package/dist/ble/setup.js.map +1 -0
- package/dist/ble/storage.d.ts +94 -0
- package/dist/ble/storage.d.ts.map +1 -0
- package/dist/ble/storage.js +132 -0
- package/dist/ble/storage.js.map +1 -0
- package/dist/ble/telink.d.ts +63 -0
- package/dist/ble/telink.d.ts.map +1 -0
- package/dist/ble/telink.js +108 -0
- package/dist/ble/telink.js.map +1 -0
- package/dist/ble/transitions.d.ts +3 -0
- package/dist/ble/transitions.d.ts.map +1 -0
- package/dist/ble/transitions.js +28 -0
- package/dist/ble/transitions.js.map +1 -0
- package/dist/ble/transport.d.ts +48 -0
- package/dist/ble/transport.d.ts.map +1 -0
- package/dist/ble/transport.js +370 -0
- package/dist/ble/transport.js.map +1 -0
- package/dist/circadian.d.ts +3 -0
- package/dist/circadian.d.ts.map +1 -1
- package/dist/circadian.js +2 -0
- package/dist/circadian.js.map +1 -1
- package/dist/cli.d.ts +3 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +125 -6
- package/dist/cli.js.map +1 -1
- package/dist/commands/__tests__/newCommands.test.js +3 -4
- package/dist/commands/__tests__/newCommands.test.js.map +1 -1
- package/dist/commands/cmdUtils.d.ts +5 -2
- package/dist/commands/cmdUtils.d.ts.map +1 -1
- package/dist/commands/cmdUtils.js +29 -10
- package/dist/commands/cmdUtils.js.map +1 -1
- package/dist/commands/daylightSimulation/autoCct.d.ts.map +1 -1
- package/dist/commands/daylightSimulation/autoCct.js +67 -197
- package/dist/commands/daylightSimulation/autoCct.js.map +1 -1
- package/dist/commands/daylightSimulation/graphSchedule.d.ts +1 -1
- package/dist/commands/daylightSimulation/graphSchedule.d.ts.map +1 -1
- package/dist/commands/daylightSimulation/printSchedule.d.ts +1 -1
- package/dist/commands/daylightSimulation/printSchedule.d.ts.map +1 -1
- package/dist/commands/daylightSimulation/printSchedule.js +2 -2
- package/dist/commands/daylightSimulation/printSchedule.js.map +1 -1
- package/dist/commands/daylightSimulation/service.d.ts +1 -1
- package/dist/commands/daylightSimulation/service.d.ts.map +1 -1
- package/dist/commands/daylightSimulation/service.js +5 -3
- package/dist/commands/daylightSimulation/service.js.map +1 -1
- package/dist/commands/daylightSimulation/simulateSchedule.d.ts +1 -1
- package/dist/commands/daylightSimulation/simulateSchedule.d.ts.map +1 -1
- package/dist/commands/daylightSimulation/simulateSchedule.js +5 -4
- package/dist/commands/daylightSimulation/simulateSchedule.js.map +1 -1
- package/dist/commands/deviceControl/ble.d.ts +4 -0
- package/dist/commands/deviceControl/ble.d.ts.map +1 -0
- package/dist/commands/deviceControl/ble.js +214 -0
- package/dist/commands/deviceControl/ble.js.map +1 -0
- package/dist/commands/deviceControl/cct.d.ts.map +1 -1
- package/dist/commands/deviceControl/cct.js +41 -11
- package/dist/commands/deviceControl/cct.js.map +1 -1
- package/dist/commands/deviceControl/color.d.ts.map +1 -1
- package/dist/commands/deviceControl/color.js +13 -3
- package/dist/commands/deviceControl/color.js.map +1 -1
- package/dist/commands/deviceControl/config.d.ts.map +1 -1
- package/dist/commands/deviceControl/config.js +26 -3
- package/dist/commands/deviceControl/config.js.map +1 -1
- package/dist/commands/deviceControl/{discover.d.ts → desktop.d.ts} +3 -2
- package/dist/commands/deviceControl/desktop.d.ts.map +1 -0
- package/dist/commands/deviceControl/desktop.js +66 -0
- package/dist/commands/deviceControl/desktop.js.map +1 -0
- package/dist/commands/deviceControl/effect.d.ts.map +1 -1
- package/dist/commands/deviceControl/effect.js +90 -159
- package/dist/commands/deviceControl/effect.js.map +1 -1
- package/dist/commands/deviceControl/fan.d.ts.map +1 -1
- package/dist/commands/deviceControl/fan.js +77 -95
- package/dist/commands/deviceControl/fan.js.map +1 -1
- package/dist/commands/deviceControl/group.d.ts.map +1 -1
- package/dist/commands/deviceControl/group.js +43 -6
- package/dist/commands/deviceControl/group.js.map +1 -1
- package/dist/commands/deviceControl/hsi.d.ts.map +1 -1
- package/dist/commands/deviceControl/hsi.js +3 -1
- package/dist/commands/deviceControl/hsi.js.map +1 -1
- package/dist/commands/deviceControl/info.d.ts.map +1 -1
- package/dist/commands/deviceControl/info.js +0 -50
- package/dist/commands/deviceControl/info.js.map +1 -1
- package/dist/commands/deviceControl/intensity.d.ts.map +1 -1
- package/dist/commands/deviceControl/intensity.js +32 -8
- package/dist/commands/deviceControl/intensity.js.map +1 -1
- package/dist/commands/deviceControl/list.d.ts.map +1 -1
- package/dist/commands/deviceControl/list.js +3 -2
- package/dist/commands/deviceControl/list.js.map +1 -1
- package/dist/commands/deviceControl/power.d.ts.map +1 -1
- package/dist/commands/deviceControl/power.js +9 -3
- package/dist/commands/deviceControl/power.js.map +1 -1
- package/dist/commands/deviceControl/preset.d.ts.map +1 -1
- package/dist/commands/deviceControl/preset.js +56 -19
- package/dist/commands/deviceControl/preset.js.map +1 -1
- package/dist/commands/deviceControl/program.d.ts +4 -0
- package/dist/commands/deviceControl/program.d.ts.map +1 -0
- package/dist/commands/deviceControl/program.js +199 -0
- package/dist/commands/deviceControl/program.js.map +1 -0
- package/dist/commands/deviceControl/quickshot.d.ts.map +1 -1
- package/dist/commands/deviceControl/quickshot.js +75 -13
- package/dist/commands/deviceControl/quickshot.js.map +1 -1
- package/dist/commands/deviceControl/scene.d.ts.map +1 -1
- package/dist/commands/deviceControl/scene.js +72 -9
- package/dist/commands/deviceControl/scene.js.map +1 -1
- package/dist/commands/deviceControl/status.d.ts.map +1 -1
- package/dist/commands/deviceControl/status.js +26 -3
- package/dist/commands/deviceControl/status.js.map +1 -1
- package/dist/commands/parseUtils.d.ts +1 -1
- package/dist/commands/parseUtils.d.ts.map +1 -1
- package/dist/commands/parseUtils.js +1 -11
- package/dist/commands/parseUtils.js.map +1 -1
- package/dist/commands-api.d.ts +1 -1
- package/dist/commands-api.d.ts.map +1 -1
- package/dist/commands-api.js +1 -1
- package/dist/commands-api.js.map +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +4 -2
- package/dist/commands.js.map +1 -1
- package/dist/config.d.ts +82 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -2
- package/dist/config.js.map +1 -1
- package/dist/daylightSimulation/cctUtil.d.ts.map +1 -1
- package/dist/daylightSimulation/cctUtil.js +2 -2
- package/dist/daylightSimulation/cctUtil.js.map +1 -1
- package/dist/daylightSimulation/constants.d.ts +10 -0
- package/dist/daylightSimulation/constants.d.ts.map +1 -1
- package/dist/daylightSimulation/constants.js +4 -0
- package/dist/daylightSimulation/constants.js.map +1 -1
- package/dist/daylightSimulation/currentCct.d.ts +42 -0
- package/dist/daylightSimulation/currentCct.d.ts.map +1 -0
- package/dist/daylightSimulation/currentCct.js +217 -0
- package/dist/daylightSimulation/currentCct.js.map +1 -0
- package/dist/daylightSimulation/dashboardSettings.d.ts +47 -0
- package/dist/daylightSimulation/dashboardSettings.d.ts.map +1 -0
- package/dist/daylightSimulation/dashboardSettings.js +95 -0
- package/dist/daylightSimulation/dashboardSettings.js.map +1 -0
- package/dist/daylightSimulation/dashboardStatus.d.ts +72 -0
- package/dist/daylightSimulation/dashboardStatus.d.ts.map +1 -0
- package/dist/daylightSimulation/dashboardStatus.js +191 -0
- package/dist/daylightSimulation/dashboardStatus.js.map +1 -0
- package/dist/daylightSimulation/parseUtils.d.ts +3 -0
- package/dist/daylightSimulation/parseUtils.d.ts.map +1 -0
- package/dist/daylightSimulation/parseUtils.js +25 -0
- package/dist/daylightSimulation/parseUtils.js.map +1 -0
- package/dist/daylightSimulation/scheduleMaker.d.ts +2 -2
- package/dist/daylightSimulation/scheduleMaker.d.ts.map +1 -1
- package/dist/daylightSimulation/scheduleMaker.js +6 -6
- package/dist/daylightSimulation/scheduleMaker.js.map +1 -1
- package/dist/daylightSimulation/types.d.ts +13 -2
- package/dist/daylightSimulation/types.d.ts.map +1 -1
- package/dist/daylightSimulation/types.js +0 -2
- package/dist/daylightSimulation/types.js.map +1 -1
- package/dist/device-control.d.ts +1 -0
- package/dist/device-control.d.ts.map +1 -1
- package/dist/device-control.js +1 -0
- package/dist/device-control.js.map +1 -1
- package/dist/deviceControl/bleHttpControl.d.ts +129 -0
- package/dist/deviceControl/bleHttpControl.d.ts.map +1 -0
- package/dist/deviceControl/bleHttpControl.js +753 -0
- package/dist/deviceControl/bleHttpControl.js.map +1 -0
- package/dist/deviceControl/lightControl.d.ts +8 -68
- package/dist/deviceControl/lightControl.d.ts.map +1 -1
- package/dist/deviceControl/lightControl.js +6 -246
- package/dist/deviceControl/lightControl.js.map +1 -1
- package/dist/deviceControl/lightControlCommands.d.ts +68 -0
- package/dist/deviceControl/lightControlCommands.d.ts.map +1 -0
- package/dist/deviceControl/lightControlCommands.js +244 -0
- package/dist/deviceControl/lightControlCommands.js.map +1 -0
- package/dist/deviceControl/types.d.ts +75 -4
- package/dist/deviceControl/types.d.ts.map +1 -1
- package/dist/deviceControl/types.js +1 -0
- package/dist/deviceControl/types.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/test/MockLightServer.d.ts +1 -0
- package/dist/test/MockLightServer.d.ts.map +1 -1
- package/dist/test/MockLightServer.js +5 -0
- package/dist/test/MockLightServer.js.map +1 -1
- package/docs/CHANGELOG.md +37 -0
- package/docs/DIRECT_BLE.md +359 -0
- package/package.json +8 -4
- package/scripts/ble-cli-check.ts +129 -0
- package/scripts/ble-config-probe.ts +109 -0
- package/scripts/ble-effects-check.ts +82 -0
- package/scripts/ble-extended-probe.ts +44 -0
- package/scripts/ble-fan-check.ts +129 -0
- package/scripts/ble-feature-probe.ts +37 -0
- package/scripts/ble-followup-check.ts +165 -0
- package/scripts/ble-hardware-check.ts +99 -0
- package/scripts/ble-live-extended-check.ts +205 -0
- package/scripts/ble-non-ota-check.ts +193 -0
- package/scripts/ble-probe.ts +45 -0
- package/scripts/calibrate-webcam.ts +152 -0
- package/scripts/desktop-reference.ts +85 -0
- package/scripts/webcam.ts +129 -0
- package/dist/__tests__/lightControl.test.d.ts +0 -2
- package/dist/__tests__/lightControl.test.d.ts.map +0 -1
- package/dist/__tests__/lightControl.test.js +0 -424
- package/dist/__tests__/lightControl.test.js.map +0 -1
- package/dist/commands/deviceControl/discover.d.ts.map +0 -1
- package/dist/commands/deviceControl/discover.js +0 -29
- package/dist/commands/deviceControl/discover.js.map +0 -1
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { validateAction } from './controller.js';
|
|
5
|
+
import { MediaSampleSchema, MediaSourceSchema, mediaCommand, mediaSamples } from './media.js';
|
|
6
|
+
export const ProgramSchema = z
|
|
7
|
+
.object({
|
|
8
|
+
kind: z.enum(['timeline', 'audio', 'picker']),
|
|
9
|
+
targets: z.union([z.literal('all'), z.array(z.string()).min(1)]),
|
|
10
|
+
duration: z.number().min(1).max(1200).default(30),
|
|
11
|
+
restore: z.boolean().default(true),
|
|
12
|
+
maxBrightness: z.number().min(0).max(100).default(100),
|
|
13
|
+
gain: z.number().positive().max(100).default(3),
|
|
14
|
+
source: MediaSourceSchema.optional(),
|
|
15
|
+
steps: z
|
|
16
|
+
.array(z
|
|
17
|
+
.object({
|
|
18
|
+
at: z.number().min(0).max(1200),
|
|
19
|
+
action: z.enum(['cct', 'hsi', 'brightness', 'color', 'gm', 'on', 'off', 'effect', 'effect-stop']),
|
|
20
|
+
args: z.record(z.unknown()),
|
|
21
|
+
})
|
|
22
|
+
.strict())
|
|
23
|
+
.min(1)
|
|
24
|
+
.max(512)
|
|
25
|
+
.optional(),
|
|
26
|
+
})
|
|
27
|
+
.strict()
|
|
28
|
+
.superRefine((program, context) => {
|
|
29
|
+
if (program.kind === 'timeline') {
|
|
30
|
+
if (!program.steps || program.source)
|
|
31
|
+
context.addIssue({ code: 'custom', message: 'A timeline needs steps and no media source' });
|
|
32
|
+
program.steps?.forEach((step, index) => {
|
|
33
|
+
if (step.at > program.duration || (index && step.at - (program.steps?.[index - 1].at ?? 0) < 0.5))
|
|
34
|
+
context.addIssue({
|
|
35
|
+
code: 'custom',
|
|
36
|
+
message: 'Steps must be ordered, at least 0.5 seconds apart, and within duration',
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
if (program.steps || !program.source)
|
|
42
|
+
context.addIssue({ code: 'custom', message: 'Media programs need a source and no timeline steps' });
|
|
43
|
+
if (program.source &&
|
|
44
|
+
(program.kind === 'audio') !==
|
|
45
|
+
(program.source.kind === 'samples'
|
|
46
|
+
? program.source.media === 'audio'
|
|
47
|
+
: ['audio-file', 'microphone'].includes(program.source.kind)))
|
|
48
|
+
context.addIssue({ code: 'custom', message: 'Media source does not match program kind' });
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
export class Programs {
|
|
52
|
+
controller;
|
|
53
|
+
targets;
|
|
54
|
+
jobs = new Map();
|
|
55
|
+
closed = false;
|
|
56
|
+
starts = Promise.resolve();
|
|
57
|
+
generations = new Map();
|
|
58
|
+
constructor(controller, targets) {
|
|
59
|
+
this.controller = controller;
|
|
60
|
+
this.targets = targets;
|
|
61
|
+
}
|
|
62
|
+
list() {
|
|
63
|
+
return [...this.jobs.values()].map((job) => structuredClone(job.status));
|
|
64
|
+
}
|
|
65
|
+
get(id) {
|
|
66
|
+
const job = this.jobs.get(id);
|
|
67
|
+
if (!job)
|
|
68
|
+
throw new Error(`Unknown program ${id}`);
|
|
69
|
+
return structuredClone(job.status);
|
|
70
|
+
}
|
|
71
|
+
async start(value) {
|
|
72
|
+
if (this.closed)
|
|
73
|
+
throw new Error('Program manager is stopping');
|
|
74
|
+
const program = ProgramSchema.parse(value);
|
|
75
|
+
const keys = this.targets(program.targets);
|
|
76
|
+
if (!keys.length)
|
|
77
|
+
throw new Error('Program has no targets');
|
|
78
|
+
for (const key of keys) {
|
|
79
|
+
const light = this.controller.config.lights.find((item) => item.key === key);
|
|
80
|
+
if (!light)
|
|
81
|
+
throw new Error(`Unknown fixture ${key}`);
|
|
82
|
+
if (program.kind === 'timeline')
|
|
83
|
+
for (const step of program.steps ?? [])
|
|
84
|
+
validateAction(light, step.action, step.args);
|
|
85
|
+
else
|
|
86
|
+
validateAction(light, program.kind === 'picker' ? 'hsi' : 'brightness', program.kind === 'picker'
|
|
87
|
+
? { hue: 0, saturation: 100, brightness: program.maxBrightness }
|
|
88
|
+
: { value: program.maxBrightness });
|
|
89
|
+
}
|
|
90
|
+
if (program.source && program.source.kind !== 'samples')
|
|
91
|
+
mediaCommand(program.source);
|
|
92
|
+
const generations = keys.map((key) => {
|
|
93
|
+
const value = (this.generations.get(key) ?? 0) + 1;
|
|
94
|
+
this.generations.set(key, value);
|
|
95
|
+
return value;
|
|
96
|
+
});
|
|
97
|
+
const previous = this.starts;
|
|
98
|
+
let release = () => undefined;
|
|
99
|
+
this.starts = new Promise((resolve) => {
|
|
100
|
+
release = resolve;
|
|
101
|
+
});
|
|
102
|
+
await previous;
|
|
103
|
+
try {
|
|
104
|
+
const superseded = () => keys.some((key, index) => this.generations.get(key) !== generations[index]);
|
|
105
|
+
if (superseded())
|
|
106
|
+
throw new Error('Program start superseded by newer control');
|
|
107
|
+
await this.cancelExisting(keys);
|
|
108
|
+
if (superseded())
|
|
109
|
+
throw new Error('Program start superseded by newer control');
|
|
110
|
+
if (this.closed)
|
|
111
|
+
throw new Error('Program manager is stopping');
|
|
112
|
+
const active = [...this.jobs.values()].filter((job) => ['running', 'preparing', 'restoring'].includes(job.status.state));
|
|
113
|
+
if (active.length >= 4)
|
|
114
|
+
throw new Error('Too many active programs');
|
|
115
|
+
for (const [id, job] of this.jobs)
|
|
116
|
+
if (this.jobs.size >= 50 && !['running', 'preparing', 'restoring'].includes(job.status.state))
|
|
117
|
+
this.jobs.delete(id);
|
|
118
|
+
const job = {
|
|
119
|
+
status: {
|
|
120
|
+
id: randomUUID(),
|
|
121
|
+
kind: program.kind,
|
|
122
|
+
targets: keys,
|
|
123
|
+
state: 'preparing',
|
|
124
|
+
startedAt: new Date().toISOString(),
|
|
125
|
+
frames: 0,
|
|
126
|
+
},
|
|
127
|
+
program,
|
|
128
|
+
cancel: new AbortController(),
|
|
129
|
+
restore: program.restore,
|
|
130
|
+
changed: false,
|
|
131
|
+
done: Promise.resolve(),
|
|
132
|
+
};
|
|
133
|
+
this.jobs.set(job.status.id, job);
|
|
134
|
+
job.done = this.run(job);
|
|
135
|
+
return structuredClone(job.status);
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
release();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
async cancelTargets(keys) {
|
|
142
|
+
for (const key of keys)
|
|
143
|
+
this.generations.set(key, (this.generations.get(key) ?? 0) + 1);
|
|
144
|
+
await this.cancelExisting(keys);
|
|
145
|
+
}
|
|
146
|
+
async cancelExisting(keys) {
|
|
147
|
+
const targets = new Set(keys);
|
|
148
|
+
const jobs = [...this.jobs.values()].filter((job) => ['running', 'preparing', 'restoring'].includes(job.status.state) &&
|
|
149
|
+
job.status.targets.some((key) => targets.has(key)));
|
|
150
|
+
for (const job of jobs) {
|
|
151
|
+
job.restore = false;
|
|
152
|
+
job.cancel.abort(new Error('Manual control or another program took over'));
|
|
153
|
+
}
|
|
154
|
+
await Promise.all(jobs.map((job) => job.done));
|
|
155
|
+
}
|
|
156
|
+
async stop(id) {
|
|
157
|
+
const job = this.jobs.get(id);
|
|
158
|
+
if (!job)
|
|
159
|
+
throw new Error(`Unknown program ${id}`);
|
|
160
|
+
job.cancel.abort(new Error('Program stopped'));
|
|
161
|
+
await job.done;
|
|
162
|
+
return structuredClone(job.status);
|
|
163
|
+
}
|
|
164
|
+
sample(id, value) {
|
|
165
|
+
const job = this.jobs.get(id);
|
|
166
|
+
if (!job ||
|
|
167
|
+
job.program.source?.kind !== 'samples' ||
|
|
168
|
+
!['preparing', 'running'].includes(job.status.state) ||
|
|
169
|
+
job.cancel.signal.aborted)
|
|
170
|
+
throw new Error('Program is not accepting live samples');
|
|
171
|
+
const sample = MediaSampleSchema.parse(value);
|
|
172
|
+
if ('rms' in sample !== (job.program.kind === 'audio'))
|
|
173
|
+
throw new Error('Sample does not match the program kind');
|
|
174
|
+
job.latest = sample;
|
|
175
|
+
job.wake?.();
|
|
176
|
+
}
|
|
177
|
+
async *inputSamples(job, signal) {
|
|
178
|
+
while (true) {
|
|
179
|
+
signal.throwIfAborted();
|
|
180
|
+
if (job.latest) {
|
|
181
|
+
const sample = job.latest;
|
|
182
|
+
job.latest = undefined;
|
|
183
|
+
yield sample;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
await new Promise((resolve, reject) => {
|
|
187
|
+
const cleanup = () => {
|
|
188
|
+
clearTimeout(timer);
|
|
189
|
+
job.wake = undefined;
|
|
190
|
+
signal.removeEventListener('abort', abort);
|
|
191
|
+
};
|
|
192
|
+
const abort = () => {
|
|
193
|
+
cleanup();
|
|
194
|
+
reject(signal.reason instanceof Error ? signal.reason : new Error('Sample stream cancelled'));
|
|
195
|
+
};
|
|
196
|
+
const timer = setTimeout(() => {
|
|
197
|
+
cleanup();
|
|
198
|
+
reject(new Error('No live samples received for 10 seconds'));
|
|
199
|
+
}, 10_000);
|
|
200
|
+
job.wake = () => {
|
|
201
|
+
cleanup();
|
|
202
|
+
resolve();
|
|
203
|
+
};
|
|
204
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
205
|
+
if (signal.aborted)
|
|
206
|
+
abort();
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async close() {
|
|
211
|
+
this.closed = true;
|
|
212
|
+
for (const job of this.jobs.values()) {
|
|
213
|
+
job.restore = false;
|
|
214
|
+
job.cancel.abort(new Error('Daemon stopped'));
|
|
215
|
+
}
|
|
216
|
+
await Promise.all([...this.jobs.values()].map((job) => job.done));
|
|
217
|
+
}
|
|
218
|
+
async command(job, action, args) {
|
|
219
|
+
job.cancel.signal.throwIfAborted();
|
|
220
|
+
job.changed = true;
|
|
221
|
+
await this.controller.batch(job.status.targets, action, args, false, job.cancel.signal);
|
|
222
|
+
job.status.frames++;
|
|
223
|
+
}
|
|
224
|
+
async run(job) {
|
|
225
|
+
const { program, cancel } = job;
|
|
226
|
+
let before;
|
|
227
|
+
let prior = {};
|
|
228
|
+
let timer;
|
|
229
|
+
let held = false;
|
|
230
|
+
try {
|
|
231
|
+
before = await this.controller.snapshot(job.status.targets);
|
|
232
|
+
cancel.signal.throwIfAborted();
|
|
233
|
+
const remaining = this.controller.overrideStatus(job.status.targets);
|
|
234
|
+
prior = Object.fromEntries(Object.entries(remaining).map(([key, ms]) => [key, ms ? Date.now() + ms : 0]));
|
|
235
|
+
if (program.kind !== 'timeline' && Object.values(before).some((state) => state.sleep || state.mode === 'effect'))
|
|
236
|
+
throw new Error('Start media control with awake fixtures in steady CCT or HSI mode');
|
|
237
|
+
await this.controller.reserveControl(job.status.targets, Math.max(30, program.duration / 60 + 1), cancel.signal);
|
|
238
|
+
held = true;
|
|
239
|
+
job.status.state = 'running';
|
|
240
|
+
const started = Date.now();
|
|
241
|
+
if (program.kind === 'timeline') {
|
|
242
|
+
for (const step of program.steps ?? []) {
|
|
243
|
+
await delay(Math.max(0, started + step.at * 1000 - Date.now()), undefined, { signal: cancel.signal });
|
|
244
|
+
await this.command(job, step.action, step.args);
|
|
245
|
+
}
|
|
246
|
+
await delay(Math.max(0, started + program.duration * 1000 - Date.now()), undefined, { signal: cancel.signal });
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
if (!program.source)
|
|
250
|
+
throw new Error('Missing media source');
|
|
251
|
+
const sourceCancel = new AbortController();
|
|
252
|
+
const cancelled = () => sourceCancel.abort(cancel.signal.reason);
|
|
253
|
+
cancel.signal.addEventListener('abort', cancelled, { once: true });
|
|
254
|
+
if (cancel.signal.aborted)
|
|
255
|
+
cancelled();
|
|
256
|
+
const sourceSignal = sourceCancel.signal;
|
|
257
|
+
const durationEnd = new Error('Media duration completed');
|
|
258
|
+
timer = setTimeout(() => sourceCancel.abort(new Error('Media capture did not start within 10 seconds')), 10_000);
|
|
259
|
+
let mediaStarted;
|
|
260
|
+
let smoothed = 0, next = 0;
|
|
261
|
+
try {
|
|
262
|
+
const samples = program.source.kind === 'samples'
|
|
263
|
+
? this.inputSamples(job, sourceSignal)
|
|
264
|
+
: mediaSamples(program.source, sourceSignal);
|
|
265
|
+
for await (const sample of samples) {
|
|
266
|
+
cancel.signal.throwIfAborted();
|
|
267
|
+
if (mediaStarted === undefined) {
|
|
268
|
+
mediaStarted = Date.now();
|
|
269
|
+
clearTimeout(timer);
|
|
270
|
+
timer = setTimeout(() => sourceCancel.abort(durationEnd), program.duration * 1000);
|
|
271
|
+
}
|
|
272
|
+
if (Date.now() >= mediaStarted + program.duration * 1000)
|
|
273
|
+
break;
|
|
274
|
+
await delay(Math.max(0, next - Date.now()), undefined, { signal: cancel.signal });
|
|
275
|
+
job.status.lastSample = sample;
|
|
276
|
+
if ('rms' in sample) {
|
|
277
|
+
smoothed = 0.35 * Math.min(1, sample.rms * program.gain) + 0.65 * smoothed;
|
|
278
|
+
await this.command(job, 'brightness', { value: Math.round(smoothed * program.maxBrightness) });
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
const hex = sample.rgb.map((value) => value.toString(16).padStart(2, '0')).join('');
|
|
282
|
+
if (hex === '000000')
|
|
283
|
+
await this.command(job, 'brightness', { value: 0 });
|
|
284
|
+
else
|
|
285
|
+
await this.command(job, 'color', { color: `#${hex}`, brightness: program.maxBrightness });
|
|
286
|
+
}
|
|
287
|
+
next = Date.now() + 500;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
if (error !== durationEnd || cancel.signal.aborted)
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
finally {
|
|
295
|
+
cancel.signal.removeEventListener('abort', cancelled);
|
|
296
|
+
}
|
|
297
|
+
if (!job.status.frames)
|
|
298
|
+
throw new Error('Media source produced no usable control frames');
|
|
299
|
+
}
|
|
300
|
+
job.status.state = 'completed';
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
job.status.state = cancel.signal.aborted ? 'cancelled' : 'failed';
|
|
304
|
+
job.status.error = error.message;
|
|
305
|
+
}
|
|
306
|
+
finally {
|
|
307
|
+
clearTimeout(timer);
|
|
308
|
+
if (before && job.restore) {
|
|
309
|
+
const outcome = job.status.state;
|
|
310
|
+
job.status.state = 'restoring';
|
|
311
|
+
try {
|
|
312
|
+
if (job.changed)
|
|
313
|
+
await this.controller.restore(before);
|
|
314
|
+
if (held)
|
|
315
|
+
for (const [key, until] of Object.entries(prior))
|
|
316
|
+
await this.controller.override([key], Math.max(0, (until - Date.now()) / 60_000));
|
|
317
|
+
job.status.state = cancel.signal.aborted && outcome !== 'failed' ? 'cancelled' : outcome;
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
job.status.state = 'failed';
|
|
321
|
+
job.status.error = `${job.status.error ? `${job.status.error}; ` : ''}Restoration failed: ${error.message}`;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (job.status.state === 'failed')
|
|
325
|
+
console.error(`Program ${job.status.id} failed: ${job.status.error}`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
//# sourceMappingURL=programs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"programs.js","sourceRoot":"","sources":["../../src/ble/programs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface UnprovisionedDevice {
|
|
2
|
+
id: string;
|
|
3
|
+
uuid: string;
|
|
4
|
+
oobInformation: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
rssi?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function provisioningAdvertisement(data: Buffer): {
|
|
9
|
+
uuid: string;
|
|
10
|
+
oobInformation: string;
|
|
11
|
+
} | undefined;
|
|
12
|
+
export declare function discoverUnprovisioned(): Promise<UnprovisionedDevice[]>;
|
|
13
|
+
//# sourceMappingURL=provisioning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provisioning.d.ts","sourceRoot":"","sources":["../../src/ble/provisioning.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AACD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAG5G;AACD,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA0B5E"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
2
|
+
import { deadline } from './async.js';
|
|
3
|
+
export function provisioningAdvertisement(data) {
|
|
4
|
+
if (data.length !== 18 && data.length !== 22)
|
|
5
|
+
return undefined;
|
|
6
|
+
return { uuid: data.subarray(0, 16).toString('hex'), oobInformation: data.subarray(16, 18).toString('hex') };
|
|
7
|
+
}
|
|
8
|
+
export async function discoverUnprovisioned() {
|
|
9
|
+
const { default: noble } = await import('@abandonware/noble');
|
|
10
|
+
if (noble._state !== 'poweredOn')
|
|
11
|
+
throw new Error('Bluetooth must be powered on before discovery');
|
|
12
|
+
const devices = new Map();
|
|
13
|
+
const discover = (peripheral) => {
|
|
14
|
+
for (const service of peripheral.advertisement.serviceData ?? []) {
|
|
15
|
+
if (service.uuid !== '1827')
|
|
16
|
+
continue;
|
|
17
|
+
const data = provisioningAdvertisement(service.data);
|
|
18
|
+
if (!data)
|
|
19
|
+
continue;
|
|
20
|
+
devices.set(data.uuid, {
|
|
21
|
+
...data,
|
|
22
|
+
id: peripheral.id,
|
|
23
|
+
name: peripheral.advertisement.localName,
|
|
24
|
+
rssi: peripheral.rssi === 127 ? undefined : peripheral.rssi,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
noble.on('discover', discover);
|
|
29
|
+
try {
|
|
30
|
+
await deadline(noble.startScanningAsync(['1827'], true), 5000, 'Provisioning scan start');
|
|
31
|
+
await delay(5000);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
noble.removeListener('discover', discover);
|
|
35
|
+
await deadline(noble.stopScanningAsync(), 3000, 'Provisioning scan stop');
|
|
36
|
+
}
|
|
37
|
+
return [...devices.values()];
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=provisioning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provisioning.js","sourceRoot":"","sources":["../../src/ble/provisioning.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAStC,MAAM,UAAU,yBAAyB,CAAC,IAAY;IACpD,IAAI,IAAI,CAAC,MAAM,KAAK,EAAE,IAAI,IAAI,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAC/D,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AAC/G,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAC9D,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnG,MAAM,OAAO,GAAG,IAAI,GAAG,EAA+B,CAAC;IACvD,MAAM,QAAQ,GAAG,CAAC,UAAsB,EAAE,EAAE;QAC1C,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,aAAa,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;YACjE,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAS;YACtC,MAAM,IAAI,GAAG,yBAAyB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACrD,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;gBACrB,GAAG,IAAI;gBACP,EAAE,EAAE,UAAU,CAAC,EAAE;gBACjB,IAAI,EAAE,UAAU,CAAC,aAAa,CAAC,SAAS;gBACxC,IAAI,EAAE,UAAU,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI;aAC5D,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,yBAAyB,CAAC,CAAC;QAC1F,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,KAAK,CAAC,cAAc,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,QAAQ,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,wBAAwB,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type IncomingMessage } from 'node:http';
|
|
2
|
+
import type { MaxLuxCalibration } from '../config.js';
|
|
3
|
+
import type { CircadianDashboardStatus } from '../daylightSimulation/dashboardStatus.js';
|
|
4
|
+
import { type VerifiedController } from './controller.js';
|
|
5
|
+
import { DashboardStore } from './dashboard.js';
|
|
6
|
+
import { LocalLibrary } from './library.js';
|
|
7
|
+
import type { MeshConfig } from './storage.js';
|
|
8
|
+
export declare function createBleServer(controller: VerifiedController, library?: LocalLibrary, options?: {
|
|
9
|
+
persistMesh?: (config: MeshConfig) => void;
|
|
10
|
+
dashboard?: DashboardStore;
|
|
11
|
+
luxCalibration?: MaxLuxCalibration;
|
|
12
|
+
luxByModel?: Partial<Record<MeshConfig['lights'][number]['model'], MaxLuxCalibration>>;
|
|
13
|
+
circadianStatus?: () => Promise<CircadianDashboardStatus>;
|
|
14
|
+
updateCircadianSettings?: (value: Record<string, unknown>) => Promise<CircadianDashboardStatus>;
|
|
15
|
+
}): import("http").Server<typeof IncomingMessage, typeof import("http").ServerResponse> & {
|
|
16
|
+
stopPrograms: () => Promise<void>;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/ble/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAE/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACzF,OAAO,EAAgB,KAAK,kBAAkB,EAAkB,MAAM,iBAAiB,CAAC;AACxF,OAAO,EACL,cAAc,EAMf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAA0B,YAAY,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAiB/C,wBAAgB,eAAe,CAC7B,UAAU,EAAE,kBAAkB,EAC9B,OAAO,eAAqB,EAC5B,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,cAAc,CAAC,EAAE,iBAAiB,CAAC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACvF,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC1D,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,wBAAwB,CAAC,CAAC;CAC5F;;EAsiBP"}
|