homebridge-nanoleaf-multi 1.0.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/.gitlab-ci.yml +24 -0
- package/README.md +9 -0
- package/dist/Device.d.ts +17 -0
- package/dist/Effect.d.ts +22 -0
- package/dist/RandomEffect.d.ts +23 -0
- package/dist/SolidEffect.d.ts +22 -0
- package/dist/WaveEffect.d.ts +23 -0
- package/dist/Zone.d.ts +26 -0
- package/dist/accessories/DynamicEffectColorAccessory.d.ts +5 -0
- package/dist/accessories/ZoneAccessory.d.ts +13 -0
- package/dist/accessories/index.d.ts +3 -0
- package/dist/constants.d.ts +9 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.LICENSE.txt +17 -0
- package/dist/platformFactory.d.ts +12 -0
- package/dist/types/Context.d.ts +9 -0
- package/dist/types/PlatformConfiguration.d.ts +6 -0
- package/dist/types/devices/DeviceConfiguration.d.ts +7 -0
- package/dist/types/devices/ZoneConfiguration.d.ts +8 -0
- package/dist/types/devices/index.d.ts +3 -0
- package/dist/types/effects/ConstantEffectColorConfiguration.d.ts +4 -0
- package/dist/types/effects/DynamicEffectColorConfiguration.d.ts +6 -0
- package/dist/types/effects/EffectColorConfiguration.d.ts +5 -0
- package/dist/types/effects/EffectColorConfigurationBase.d.ts +3 -0
- package/dist/types/effects/EffectColorType.d.ts +6 -0
- package/dist/types/effects/EffectConfiguration.d.ts +5 -0
- package/dist/types/effects/EffectConfigurationBase.d.ts +8 -0
- package/dist/types/effects/EffectType.d.ts +6 -0
- package/dist/types/effects/RemoteEffectColorConfiguration.d.ts +4 -0
- package/dist/types/effects/index.d.ts +14 -0
- package/dist/types/effects/native/NativeDirection.d.ts +7 -0
- package/dist/types/effects/native/NativeEffect.d.ts +13 -0
- package/dist/types/effects/native/NativeEffectColor.d.ts +6 -0
- package/dist/types/effects/native/NativeEffectOption.d.ts +18 -0
- package/dist/types/effects/native/NativeEffectType.d.ts +9 -0
- package/dist/types/effects/native/index.d.ts +6 -0
- package/dist/types/effects/random-effect/RandomEffectConfiguration.d.ts +9 -0
- package/dist/types/effects/random-effect/index.d.ts +2 -0
- package/dist/types/effects/solid-effect/SolidEffectColorConfiguration.d.ts +4 -0
- package/dist/types/effects/solid-effect/SolidEffectConfiguration.d.ts +7 -0
- package/dist/types/effects/solid-effect/index.d.ts +3 -0
- package/dist/types/effects/wave-effect/WaveEffectConfiguration.d.ts +11 -0
- package/dist/types/effects/wave-effect/index.d.ts +2 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/utilities/HomebridgeLogAppender.d.ts +7 -0
- package/dist/utilities/colorToNanoleafColor.d.ts +4 -0
- package/dist/utilities/index.d.ts +4 -0
- package/dist/utilities/nativeEffectTypeToPluginUuid.d.ts +3 -0
- package/package.json +52 -0
- package/src/Device.ts +73 -0
- package/src/Effect.ts +80 -0
- package/src/RandomEffect.ts +82 -0
- package/src/SolidEffect.ts +38 -0
- package/src/WaveEffect.ts +95 -0
- package/src/Zone.ts +151 -0
- package/src/accessories/DynamicEffectColorAccessory.ts +19 -0
- package/src/accessories/ZoneAccessory.ts +46 -0
- package/src/accessories/index.ts +4 -0
- package/src/constants.ts +32 -0
- package/src/index.ts +11 -0
- package/src/platformFactory.ts +88 -0
- package/src/types/Context.ts +10 -0
- package/src/types/PlatformConfiguration.ts +7 -0
- package/src/types/devices/DeviceConfiguration.ts +7 -0
- package/src/types/devices/ZoneConfiguration.ts +9 -0
- package/src/types/devices/index.ts +4 -0
- package/src/types/effects/ConstantEffectColorConfiguration.ts +9 -0
- package/src/types/effects/DynamicEffectColorConfiguration.ts +12 -0
- package/src/types/effects/EffectColorConfiguration.ts +10 -0
- package/src/types/effects/EffectColorConfigurationBase.ts +3 -0
- package/src/types/effects/EffectColorType.ts +9 -0
- package/src/types/effects/EffectConfiguration.ts +10 -0
- package/src/types/effects/EffectConfigurationBase.ts +9 -0
- package/src/types/effects/EffectType.ts +7 -0
- package/src/types/effects/RemoteEffectColorConfiguration.ts +9 -0
- package/src/types/effects/index.ts +25 -0
- package/src/types/effects/native/NativeDirection.ts +8 -0
- package/src/types/effects/native/NativeEffect.ts +14 -0
- package/src/types/effects/native/NativeEffectColor.ts +6 -0
- package/src/types/effects/native/NativeEffectOption.ts +25 -0
- package/src/types/effects/native/NativeEffectType.ts +10 -0
- package/src/types/effects/native/index.ts +13 -0
- package/src/types/effects/random-effect/RandomEffectConfiguration.ts +11 -0
- package/src/types/effects/random-effect/index.ts +3 -0
- package/src/types/effects/solid-effect/SolidEffectColorConfiguration.ts +8 -0
- package/src/types/effects/solid-effect/SolidEffectConfiguration.ts +9 -0
- package/src/types/effects/solid-effect/index.ts +4 -0
- package/src/types/effects/wave-effect/WaveEffectConfiguration.ts +13 -0
- package/src/types/effects/wave-effect/index.ts +3 -0
- package/src/types/index.ts +6 -0
- package/src/utilities/HomebridgeLogAppender.ts +15 -0
- package/src/utilities/colorToNanoleafColor.ts +14 -0
- package/src/utilities/index.ts +9 -0
- package/src/utilities/nativeEffectTypeToPluginUuid.ts +4 -0
- package/tsconfig.json +21 -0
- package/webpack.config.js +42 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ColorHSV,
|
|
3
|
+
colorToColorHSV,
|
|
4
|
+
ColorType as CoreColorType,
|
|
5
|
+
} from '@manganese/palette-kit-core';
|
|
6
|
+
import { ClientColorType } from '@manganese/palette-kit-client';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
Context,
|
|
10
|
+
WaveEffectConfiguration,
|
|
11
|
+
EffectColorConfiguration,
|
|
12
|
+
ConstantEffectColorConfiguration,
|
|
13
|
+
DynamicEffectColorConfiguration,
|
|
14
|
+
RemoteEffectColorConfiguration,
|
|
15
|
+
NativeEffectType,
|
|
16
|
+
NativeEffectOption,
|
|
17
|
+
} from './types';
|
|
18
|
+
import { EFFECT_SPEED_COEFFICIENT, NATIVE_EFFECT_BASE } from './constants';
|
|
19
|
+
import {
|
|
20
|
+
colorToNanoleafColor,
|
|
21
|
+
nativeEffectTypeToPluginUuid,
|
|
22
|
+
} from './utilities';
|
|
23
|
+
import Effect from './Effect';
|
|
24
|
+
import Device from './Device';
|
|
25
|
+
|
|
26
|
+
export default class WaveEffect extends Effect<WaveEffectConfiguration> {
|
|
27
|
+
private colors = new Map<string /* color ID */, ColorHSV>();
|
|
28
|
+
|
|
29
|
+
constructor(configuration: WaveEffectConfiguration, context: Context) {
|
|
30
|
+
super(configuration, context);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public async initialize() {}
|
|
34
|
+
|
|
35
|
+
private getColor(colorConfiguration: EffectColorConfiguration) {
|
|
36
|
+
switch (colorConfiguration.type) {
|
|
37
|
+
case CoreColorType.Constant:
|
|
38
|
+
return colorToColorHSV(
|
|
39
|
+
(colorConfiguration as ConstantEffectColorConfiguration).color
|
|
40
|
+
);
|
|
41
|
+
case CoreColorType.Dynamic:
|
|
42
|
+
case ClientColorType.Remote:
|
|
43
|
+
return this.colors.get(
|
|
44
|
+
(
|
|
45
|
+
colorConfiguration as
|
|
46
|
+
| DynamicEffectColorConfiguration
|
|
47
|
+
| RemoteEffectColorConfiguration
|
|
48
|
+
).id
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public getNativeEffectForDevice(device: Device) {
|
|
54
|
+
const colorsPerFrame =
|
|
55
|
+
1 + Math.ceil(device.size / this.configuration.colorSize);
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
...NATIVE_EFFECT_BASE,
|
|
59
|
+
...this.nativeEffectBase,
|
|
60
|
+
pluginUuid: nativeEffectTypeToPluginUuid(NativeEffectType.Wheel),
|
|
61
|
+
pluginOptions: [
|
|
62
|
+
{
|
|
63
|
+
name: 'linDirection',
|
|
64
|
+
value: this.configuration.direction,
|
|
65
|
+
} as NativeEffectOption,
|
|
66
|
+
{
|
|
67
|
+
name: 'loop',
|
|
68
|
+
value: true,
|
|
69
|
+
} as NativeEffectOption,
|
|
70
|
+
{
|
|
71
|
+
name: 'nColorsPerFrame',
|
|
72
|
+
value: colorsPerFrame,
|
|
73
|
+
} as NativeEffectOption,
|
|
74
|
+
{
|
|
75
|
+
name: 'transTime',
|
|
76
|
+
value: this.configuration.transitionTime / colorsPerFrame,
|
|
77
|
+
} as NativeEffectOption,
|
|
78
|
+
],
|
|
79
|
+
palette: this.configuration.colors.map((colorConfiguration) => {
|
|
80
|
+
const color = this.getColor(colorConfiguration);
|
|
81
|
+
|
|
82
|
+
return colorToNanoleafColor(color, colorConfiguration.probability);
|
|
83
|
+
}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public getColors() {
|
|
88
|
+
return this.configuration.colors;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public setColor(colorId: string, color: ColorHSV) {
|
|
92
|
+
this.colors.set(colorId, color);
|
|
93
|
+
this.handleChange();
|
|
94
|
+
}
|
|
95
|
+
}
|
package/src/Zone.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Context,
|
|
3
|
+
ZoneConfiguration,
|
|
4
|
+
EffectType,
|
|
5
|
+
EffectConfiguration,
|
|
6
|
+
EffectConfigurationBase,
|
|
7
|
+
SolidEffectConfiguration,
|
|
8
|
+
WaveEffectConfiguration,
|
|
9
|
+
RandomEffectConfiguration,
|
|
10
|
+
} from './types';
|
|
11
|
+
import { EFFECT_CHANGE_EVENT } from './constants';
|
|
12
|
+
|
|
13
|
+
import Device from './Device';
|
|
14
|
+
import Effect from './Effect';
|
|
15
|
+
import SolidEffect from './SolidEffect';
|
|
16
|
+
import WaveEffect from './WaveEffect';
|
|
17
|
+
import RandomEffect from './RandomEffect';
|
|
18
|
+
|
|
19
|
+
export default class Zone {
|
|
20
|
+
public readonly configuration: ZoneConfiguration;
|
|
21
|
+
private context: Context;
|
|
22
|
+
|
|
23
|
+
constructor(configuration: ZoneConfiguration, context: Context) {
|
|
24
|
+
this.configuration = configuration;
|
|
25
|
+
this.context = context;
|
|
26
|
+
|
|
27
|
+
configuration.devices.forEach((deviceConfiguration) => {
|
|
28
|
+
const device = new Device(deviceConfiguration, context);
|
|
29
|
+
|
|
30
|
+
this.devices.add(device);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
this.configuration.effects?.forEach((effectConfiguration) => {
|
|
34
|
+
const effect = this.createEffect(effectConfiguration);
|
|
35
|
+
effect.on(EFFECT_CHANGE_EVENT, () => {
|
|
36
|
+
if (this.activeEffectId !== effect.id) return;
|
|
37
|
+
|
|
38
|
+
// TODO log
|
|
39
|
+
|
|
40
|
+
this.setActiveEffect(effect);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
this.effects.set(effect.id, effect);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public get name() {
|
|
48
|
+
return this.configuration.name;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public get id() {
|
|
52
|
+
return this.configuration.id;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public createEffect(configuration: EffectConfiguration) {
|
|
56
|
+
switch (configuration.type) {
|
|
57
|
+
case EffectType.Solid:
|
|
58
|
+
return new SolidEffect(
|
|
59
|
+
configuration as SolidEffectConfiguration,
|
|
60
|
+
this.context
|
|
61
|
+
);
|
|
62
|
+
case EffectType.Wave:
|
|
63
|
+
return new WaveEffect(
|
|
64
|
+
configuration as WaveEffectConfiguration,
|
|
65
|
+
this.context
|
|
66
|
+
);
|
|
67
|
+
case EffectType.Random:
|
|
68
|
+
return new RandomEffect(
|
|
69
|
+
configuration as RandomEffectConfiguration,
|
|
70
|
+
this.context
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Initialization
|
|
76
|
+
public async initialize() {
|
|
77
|
+
await Promise.all(
|
|
78
|
+
this.devicesArray.map(async (device) => {
|
|
79
|
+
try {
|
|
80
|
+
await device.initialize();
|
|
81
|
+
} catch (error) {
|
|
82
|
+
this.context.log.error(
|
|
83
|
+
`Failed to initialize device <${device.name}>`,
|
|
84
|
+
error
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Devices
|
|
92
|
+
private devices = new Set<Device>();
|
|
93
|
+
|
|
94
|
+
private get devicesArray() {
|
|
95
|
+
return Array.from(this.devices);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public async setActive(active: boolean) {
|
|
99
|
+
await Promise.all(
|
|
100
|
+
this.devicesArray.map(async (device) => {
|
|
101
|
+
await device.setActive(active);
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Effects
|
|
107
|
+
private effects = new Map<string, Effect<any>>();
|
|
108
|
+
private activeEffectId: string;
|
|
109
|
+
|
|
110
|
+
public getEffects() {
|
|
111
|
+
return this.effects;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public getEffect<T extends Effect<any> = Effect<EffectConfigurationBase>>(
|
|
115
|
+
effectId: string
|
|
116
|
+
): T | null {
|
|
117
|
+
const effect = this.effects.get(effectId);
|
|
118
|
+
|
|
119
|
+
return (effect as T) || null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public get activeEffect() {
|
|
123
|
+
return this.getEffect(this.activeEffectId);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public getDefaultActiveEffectId() {
|
|
127
|
+
if (this.effects.size === 0) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return Array.from(this.effects.values())[0].id;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public async setActiveEffectById(effectId: string) {
|
|
135
|
+
this.activeEffectId = effectId;
|
|
136
|
+
|
|
137
|
+
await this.setActiveEffect(this.activeEffect);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public async setActiveEffect(effect: Effect<any>) {
|
|
141
|
+
await Promise.all(
|
|
142
|
+
Array.from(this.devices).map((device) => {
|
|
143
|
+
device.setActiveEffect(effect);
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public getActiveEffectId() {
|
|
149
|
+
return this.activeEffectId;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { LocalPaletteColorAccessory } from 'helpers-for-homebridge';
|
|
2
|
+
import { Context, DynamicEffectColorConfiguration } from '../types';
|
|
3
|
+
|
|
4
|
+
export default class DynamicEffectColorAccessory extends LocalPaletteColorAccessory {
|
|
5
|
+
constructor(
|
|
6
|
+
colorConfiguration: DynamicEffectColorConfiguration,
|
|
7
|
+
context: Context
|
|
8
|
+
) {
|
|
9
|
+
super(
|
|
10
|
+
context.palette,
|
|
11
|
+
{
|
|
12
|
+
...colorConfiguration,
|
|
13
|
+
name: colorConfiguration.name,
|
|
14
|
+
colorId: colorConfiguration.id,
|
|
15
|
+
},
|
|
16
|
+
context
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { SelectionAccessory } from 'helpers-for-homebridge';
|
|
2
|
+
import { Context } from '../types';
|
|
3
|
+
import Zone from '../Zone';
|
|
4
|
+
|
|
5
|
+
export default class ZoneAccessory extends SelectionAccessory {
|
|
6
|
+
constructor(private readonly zone: Zone, context: Context) {
|
|
7
|
+
super(
|
|
8
|
+
{
|
|
9
|
+
name: zone.name,
|
|
10
|
+
options: zone.configuration.effects.map((effectConfiguration) => {
|
|
11
|
+
return {
|
|
12
|
+
name: effectConfiguration.name,
|
|
13
|
+
id: effectConfiguration.id,
|
|
14
|
+
hapIdentifier: effectConfiguration.hapIdentifier,
|
|
15
|
+
};
|
|
16
|
+
}),
|
|
17
|
+
},
|
|
18
|
+
context
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
this.activeOptionId = this.configuration.options[0].id;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private active: boolean = false;
|
|
25
|
+
private activeOptionId: string;
|
|
26
|
+
|
|
27
|
+
protected override async getActiveOptionId() {
|
|
28
|
+
return this.activeOptionId;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
protected override async setActiveOptionId(effectId: string) {
|
|
32
|
+
this.activeOptionId = effectId;
|
|
33
|
+
|
|
34
|
+
await this.zone.setActiveEffectById(effectId);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protected override async getActive() {
|
|
38
|
+
return this.active;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected override async setActive(active: boolean) {
|
|
42
|
+
this.active = active;
|
|
43
|
+
|
|
44
|
+
await this.zone.setActive(active);
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ColorHSV, ColorSpace } from '@manganese/palette-kit-core';
|
|
2
|
+
import { NativeEffect, NativeEffectType } from './types';
|
|
3
|
+
|
|
4
|
+
export const OFF_COLOR: ColorHSV = {
|
|
5
|
+
space: ColorSpace.HSV,
|
|
6
|
+
hue: 0,
|
|
7
|
+
saturation: 0,
|
|
8
|
+
value: 0,
|
|
9
|
+
};
|
|
10
|
+
export const DEFAULT_DEVICE_SIZE = 50;
|
|
11
|
+
export const EFFECT_CHANGE_EVENT = 'change';
|
|
12
|
+
export const EFFECT_SPEED_COEFFICIENT = 300;
|
|
13
|
+
export const DEFAULT_NATIVE_EFFECT_NAME = 'Dynamic Effect';
|
|
14
|
+
export const NATIVE_EFFECT_TYPE_UUIDS = new Map<NativeEffectType, string>([
|
|
15
|
+
[NativeEffectType.Wheel, '6970681a-20b5-4c5e-8813-bdaebc4ee4fa'],
|
|
16
|
+
[NativeEffectType.Flow, '027842e4-e1d6-4a4c-a731-be74a1ebd4cf'],
|
|
17
|
+
[NativeEffectType.Explode, '713518c1-d560-47db-8991-de780af71d1e'],
|
|
18
|
+
[NativeEffectType.Fade, 'b3fd723a-aae8-4c99-bf2b-087159e0ef53'],
|
|
19
|
+
[NativeEffectType.Random, 'ba632d3e-9c2b-4413-a965-510c839b3f71'],
|
|
20
|
+
[NativeEffectType.Highlight, '70b7c636-6bf8-491f-89c1-f4103508d642'],
|
|
21
|
+
]);
|
|
22
|
+
export const NATIVE_EFFECT_BASE: NativeEffect = {
|
|
23
|
+
version: '2.0',
|
|
24
|
+
animName: DEFAULT_NATIVE_EFFECT_NAME,
|
|
25
|
+
animType: 'plugin',
|
|
26
|
+
colorType: 'HSB',
|
|
27
|
+
palette: [],
|
|
28
|
+
pluginType: 'color',
|
|
29
|
+
pluginUuid: NATIVE_EFFECT_TYPE_UUIDS.get(NativeEffectType.Fade),
|
|
30
|
+
pluginOptions: [],
|
|
31
|
+
hasOverlay: false,
|
|
32
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createSimpleLogger, Logger } from 'simple-node-logger';
|
|
2
|
+
import { HomebridgeLogAppender } from 'helpers-for-homebridge';
|
|
3
|
+
import { Palette } from '@manganese/palette-kit-core';
|
|
4
|
+
import { PaletteClient } from '@manganese/palette-kit-client';
|
|
5
|
+
|
|
6
|
+
import { PlatformConfiguration, Context } from './types';
|
|
7
|
+
import { DynamicEffectColorAccessory, ZoneAccessory } from './accessories';
|
|
8
|
+
import Zone from './Zone';
|
|
9
|
+
|
|
10
|
+
export default (homebridge: any) => {
|
|
11
|
+
class Platform {
|
|
12
|
+
context: Context;
|
|
13
|
+
zones = new Map<string /* zone ID */, Zone>();
|
|
14
|
+
|
|
15
|
+
get allEffects() {
|
|
16
|
+
return Array.from(this.zones.values()).flatMap((zone) =>
|
|
17
|
+
Array.from(zone.getEffects().values())
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
constructor(homebridgeLog, readonly configuration: PlatformConfiguration) {
|
|
22
|
+
const log = createSimpleLogger({
|
|
23
|
+
loggers: [
|
|
24
|
+
new Logger({
|
|
25
|
+
appenders: [new HomebridgeLogAppender(homebridgeLog)],
|
|
26
|
+
}),
|
|
27
|
+
],
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const palette = new Palette({}, { log });
|
|
31
|
+
palette.onAnyColorChange((event) => {
|
|
32
|
+
this.allEffects.forEach((effect) => {
|
|
33
|
+
if (!effect.hasColor(event.colorId)) return;
|
|
34
|
+
|
|
35
|
+
effect.setColor(event.colorId, event.colorHsv);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const paletteClient = new PaletteClient(
|
|
40
|
+
configuration.paletteClient,
|
|
41
|
+
{
|
|
42
|
+
log,
|
|
43
|
+
},
|
|
44
|
+
palette
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
this.context = {
|
|
48
|
+
homebridge,
|
|
49
|
+
log,
|
|
50
|
+
palette,
|
|
51
|
+
paletteClient,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
this.configuration.zones.forEach((zoneConfiguration) => {
|
|
55
|
+
const zone = new Zone(zoneConfiguration, this.context);
|
|
56
|
+
|
|
57
|
+
this.zones.set(zoneConfiguration.id, zone);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public async accessories(callback) {
|
|
62
|
+
await this.context.paletteClient.connect();
|
|
63
|
+
|
|
64
|
+
const zoneAccessories = await Promise.all(
|
|
65
|
+
Array.from(this.zones.values()).map(async (zone) => {
|
|
66
|
+
await zone.initialize();
|
|
67
|
+
|
|
68
|
+
return new ZoneAccessory(zone, this.context);
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const effectAccessories = this.allEffects.flatMap((effect) => {
|
|
73
|
+
return effect.getDynamicColors().map((colorConfiguration) => {
|
|
74
|
+
return new DynamicEffectColorAccessory(
|
|
75
|
+
colorConfiguration,
|
|
76
|
+
this.context
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const accessories = [...zoneAccessories, ...effectAccessories];
|
|
82
|
+
|
|
83
|
+
callback(accessories);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return Platform;
|
|
88
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PaletteClient } from '@manganese/palette-kit-client';
|
|
2
|
+
import { Palette } from '@manganese/palette-kit-core';
|
|
3
|
+
import SimpleLogger from 'simple-node-logger';
|
|
4
|
+
|
|
5
|
+
export default interface Context {
|
|
6
|
+
homebridge: any;
|
|
7
|
+
palette: Palette;
|
|
8
|
+
paletteClient: PaletteClient;
|
|
9
|
+
log: SimpleLogger.Logger;
|
|
10
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import DeviceConfiguration from './DeviceConfiguration';
|
|
2
|
+
import EffectConfiguration from '../effects/EffectConfiguration';
|
|
3
|
+
|
|
4
|
+
export default interface ZoneConfiguration {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
devices: DeviceConfiguration[];
|
|
8
|
+
effects: EffectConfiguration[];
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ConstantColorConfiguration } from '@manganese/palette-kit-core';
|
|
2
|
+
import EffectColorConfigurationBase from './EffectColorConfigurationBase';
|
|
3
|
+
|
|
4
|
+
type ConstantEffectColorConfiguration<AdditionalConfigurationType = {}> =
|
|
5
|
+
ConstantColorConfiguration<
|
|
6
|
+
EffectColorConfigurationBase & AdditionalConfigurationType
|
|
7
|
+
>;
|
|
8
|
+
|
|
9
|
+
export default ConstantEffectColorConfiguration;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DynamicColorConfiguration } from '@manganese/palette-kit-core';
|
|
2
|
+
import EffectColorConfigurationBase from './EffectColorConfigurationBase';
|
|
3
|
+
|
|
4
|
+
type DynamicEffectColorConfiguration<AdditionalConfigurationType = {}> =
|
|
5
|
+
DynamicColorConfiguration<
|
|
6
|
+
EffectColorConfigurationBase &
|
|
7
|
+
AdditionalConfigurationType & {
|
|
8
|
+
name: string;
|
|
9
|
+
}
|
|
10
|
+
>;
|
|
11
|
+
|
|
12
|
+
export default DynamicEffectColorConfiguration;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import ConstantEffectColorConfiguration from './ConstantEffectColorConfiguration';
|
|
2
|
+
import DynamicEffectColorConfiguration from './DynamicEffectColorConfiguration';
|
|
3
|
+
import RemoteEffectColorConfiguration from './RemoteEffectColorConfiguration';
|
|
4
|
+
|
|
5
|
+
type EffectColorConfiguration =
|
|
6
|
+
| ConstantEffectColorConfiguration
|
|
7
|
+
| DynamicEffectColorConfiguration
|
|
8
|
+
| RemoteEffectColorConfiguration;
|
|
9
|
+
|
|
10
|
+
export default EffectColorConfiguration;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RandomEffectConfiguration } from './random-effect';
|
|
2
|
+
import { SolidEffectConfiguration } from './solid-effect';
|
|
3
|
+
import { WaveEffectConfiguration } from './wave-effect';
|
|
4
|
+
|
|
5
|
+
type EffectConfiguration =
|
|
6
|
+
| SolidEffectConfiguration
|
|
7
|
+
| WaveEffectConfiguration
|
|
8
|
+
| RandomEffectConfiguration;
|
|
9
|
+
|
|
10
|
+
export default EffectConfiguration;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RemoteColorConfiguration } from '@manganese/palette-kit-client';
|
|
2
|
+
import EffectColorConfigurationBase from './EffectColorConfigurationBase';
|
|
3
|
+
|
|
4
|
+
type RemoteEffectColorConfiguration<AdditionalConfigurationType = {}> =
|
|
5
|
+
RemoteColorConfiguration<
|
|
6
|
+
EffectColorConfigurationBase & AdditionalConfigurationType
|
|
7
|
+
>;
|
|
8
|
+
|
|
9
|
+
export default RemoteEffectColorConfiguration;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import EffectType from './EffectType';
|
|
2
|
+
import EffectConfiguration from './EffectConfiguration';
|
|
3
|
+
import EffectConfigurationBase from './EffectConfigurationBase';
|
|
4
|
+
import EffectColorType from './EffectColorType';
|
|
5
|
+
import EffectColorConfiguration from './EffectColorConfiguration';
|
|
6
|
+
import EffectColorConfigurationBase from './EffectColorConfigurationBase';
|
|
7
|
+
import ConstantEffectColorConfiguration from './ConstantEffectColorConfiguration';
|
|
8
|
+
import DynamicEffectColorConfiguration from './DynamicEffectColorConfiguration';
|
|
9
|
+
import RemoteEffectColorConfiguration from './RemoteEffectColorConfiguration';
|
|
10
|
+
|
|
11
|
+
export * from './native';
|
|
12
|
+
export * from './solid-effect';
|
|
13
|
+
export * from './wave-effect';
|
|
14
|
+
export * from './random-effect';
|
|
15
|
+
export {
|
|
16
|
+
EffectType,
|
|
17
|
+
EffectConfiguration,
|
|
18
|
+
EffectConfigurationBase,
|
|
19
|
+
EffectColorType,
|
|
20
|
+
EffectColorConfiguration,
|
|
21
|
+
EffectColorConfigurationBase,
|
|
22
|
+
ConstantEffectColorConfiguration,
|
|
23
|
+
DynamicEffectColorConfiguration,
|
|
24
|
+
RemoteEffectColorConfiguration,
|
|
25
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import NativeEffectColor from './NativeEffectColor';
|
|
2
|
+
import NativeEffectOption from './NativeEffectOption';
|
|
3
|
+
|
|
4
|
+
export default interface NativeEffect {
|
|
5
|
+
version: '2.0';
|
|
6
|
+
animName: string;
|
|
7
|
+
animType: 'plugin';
|
|
8
|
+
colorType: 'HSB';
|
|
9
|
+
palette: NativeEffectColor[];
|
|
10
|
+
pluginType: 'color';
|
|
11
|
+
pluginUuid: string;
|
|
12
|
+
pluginOptions: NativeEffectOption[];
|
|
13
|
+
hasOverlay: false;
|
|
14
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import NativeDirection from './NativeDirection';
|
|
2
|
+
|
|
3
|
+
type NativeEffectOption =
|
|
4
|
+
| {
|
|
5
|
+
name: 'delayTime';
|
|
6
|
+
value: number;
|
|
7
|
+
}
|
|
8
|
+
| {
|
|
9
|
+
name: 'transTime';
|
|
10
|
+
value: number;
|
|
11
|
+
}
|
|
12
|
+
| {
|
|
13
|
+
name: 'linDirection';
|
|
14
|
+
value: NativeDirection;
|
|
15
|
+
}
|
|
16
|
+
| {
|
|
17
|
+
name: 'loop';
|
|
18
|
+
value: boolean;
|
|
19
|
+
}
|
|
20
|
+
| {
|
|
21
|
+
name: 'nColorsPerFrame';
|
|
22
|
+
value: number;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default NativeEffectOption;
|