iobroker.loxone 3.0.1 → 4.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/LICENSE +183 -183
- package/README.md +417 -411
- package/admin/i18n/de.json +15 -0
- package/admin/i18n/en.json +15 -0
- package/admin/i18n/es.json +18 -0
- package/admin/i18n/fr.json +18 -0
- package/admin/i18n/it.json +18 -0
- package/admin/i18n/nl.json +18 -0
- package/admin/i18n/pl.json +18 -0
- package/admin/i18n/pt.json +18 -0
- package/admin/i18n/ru.json +18 -0
- package/admin/i18n/uk.json +18 -0
- package/admin/i18n/zh-cn.json +18 -0
- package/admin/jsonConfig.json +96 -0
- package/io-package.json +49 -38
- package/package.json +36 -49
- package/src/controls/AalEmergency.ts +90 -0
- package/src/controls/AalSmartAlarm.ts +99 -0
- package/src/controls/Alarm.ts +146 -0
- package/src/controls/AlarmClock.ts +137 -0
- package/src/controls/Application.ts +13 -0
- package/src/controls/AudioZone.ts +227 -0
- package/src/controls/AudioZoneV2.ts +135 -0
- package/src/controls/CentralAlarm.ts +59 -0
- package/src/controls/CentralAudioZone.ts +41 -0
- package/src/controls/CentralGate.ts +53 -0
- package/src/controls/CentralJalousie.ts +67 -0
- package/src/controls/CentralLightController.ts +45 -0
- package/src/controls/ColorPickerV2.ts +34 -0
- package/src/controls/Colorpicker.ts +30 -0
- package/src/controls/ColorpickerBase.ts +326 -0
- package/src/controls/Daytimer.ts +201 -0
- package/src/controls/Dimmer.ts +64 -0
- package/src/controls/EIBDimmer.ts +61 -0
- package/src/controls/Fronius.ts +217 -0
- package/src/controls/Gate.ts +150 -0
- package/src/controls/Hourcounter.ts +115 -0
- package/src/controls/IRCDaytimer.ts +4 -0
- package/src/controls/IRCV2Daytimer.ts +4 -0
- package/src/controls/IRoomControllerV2.ts +595 -0
- package/src/controls/InfoOnlyAnalog.ts +56 -0
- package/src/controls/InfoOnlyDigital.ts +95 -0
- package/src/controls/InfoOnlyText.ts +52 -0
- package/{build/controls/Intercom.js → src/controls/Intercom.ts} +27 -11
- package/src/controls/Jalousie.ts +219 -0
- package/src/controls/LightController.ts +112 -0
- package/src/controls/LightControllerV2.ts +246 -0
- package/src/controls/MailBox.ts +92 -0
- package/src/controls/Meter.ts +94 -0
- package/src/controls/None.ts +29 -0
- package/src/controls/PresenceDetector.ts +47 -0
- package/src/controls/Pushbutton.ts +55 -0
- package/src/controls/Radio.ts +61 -0
- package/{build/controls/Remote.js → src/controls/Remote.ts} +19 -11
- package/src/controls/Slider.ts +78 -0
- package/src/controls/SmokeAlarm.ts +163 -0
- package/src/controls/Switch.ts +46 -0
- package/src/controls/SystemScheme.ts +13 -0
- package/src/controls/TextInput.ts +96 -0
- package/src/controls/TextState.ts +37 -0
- package/src/controls/TimedSwitch.ts +75 -0
- package/src/controls/Tracker.ts +30 -0
- package/{build/controls/Unknown.js → src/controls/Unknown.ts} +18 -11
- package/src/controls/UpDownAnalog.ts +78 -0
- package/{build/controls/ValueSelector.js → src/controls/ValueSelector.ts} +21 -9
- package/src/controls/WindowMonitor.ts +139 -0
- package/src/controls/all-controls.ts +99 -0
- package/src/controls/control-base.ts +28 -0
- package/src/lib/adapter-config.d.ts +22 -0
- package/src/loxone-handler-base.ts +285 -0
- package/src/lxcommunicator.d.ts +1 -0
- package/src/main.test.ts +24 -0
- package/{build/main.js → src/main.ts} +545 -270
- package/src/structure-file.d.ts +154 -0
- package/src/weather-server-handler.ts +266 -0
- package/admin/admin.d.ts +0 -58
- package/admin/index_m.html +0 -126
- package/admin/style.css +0 -32
- package/admin/words.js +0 -25
- package/build/controls/AalEmergency.js +0 -45
- package/build/controls/AalEmergency.js.map +0 -1
- package/build/controls/AalSmartAlarm.js +0 -48
- package/build/controls/AalSmartAlarm.js.map +0 -1
- package/build/controls/Alarm.js +0 -81
- package/build/controls/Alarm.js.map +0 -1
- package/build/controls/AlarmClock.js +0 -59
- package/build/controls/AlarmClock.js.map +0 -1
- package/build/controls/Application.js +0 -11
- package/build/controls/Application.js.map +0 -1
- package/build/controls/AudioZone.js +0 -116
- package/build/controls/AudioZone.js.map +0 -1
- package/build/controls/CentralAlarm.js +0 -30
- package/build/controls/CentralAlarm.js.map +0 -1
- package/build/controls/CentralAudioZone.js +0 -22
- package/build/controls/CentralAudioZone.js.map +0 -1
- package/build/controls/CentralGate.js +0 -30
- package/build/controls/CentralGate.js.map +0 -1
- package/build/controls/CentralJalousie.js +0 -39
- package/build/controls/CentralJalousie.js.map +0 -1
- package/build/controls/CentralLightController.js +0 -27
- package/build/controls/CentralLightController.js.map +0 -1
- package/build/controls/ColorPickerV2.js +0 -24
- package/build/controls/ColorPickerV2.js.map +0 -1
- package/build/controls/Colorpicker.js +0 -20
- package/build/controls/Colorpicker.js.map +0 -1
- package/build/controls/ColorpickerBase.js +0 -263
- package/build/controls/ColorpickerBase.js.map +0 -1
- package/build/controls/Daytimer.js +0 -119
- package/build/controls/Daytimer.js.map +0 -1
- package/build/controls/Dimmer.js +0 -34
- package/build/controls/Dimmer.js.map +0 -1
- package/build/controls/EIBDimmer.js +0 -31
- package/build/controls/EIBDimmer.js.map +0 -1
- package/build/controls/Fronius.js +0 -64
- package/build/controls/Fronius.js.map +0 -1
- package/build/controls/Gate.js +0 -104
- package/build/controls/Gate.js.map +0 -1
- package/build/controls/Hourcounter.js +0 -46
- package/build/controls/Hourcounter.js.map +0 -1
- package/build/controls/IRCDaytimer.js +0 -9
- package/build/controls/IRCDaytimer.js.map +0 -1
- package/build/controls/IRCV2Daytimer.js +0 -9
- package/build/controls/IRCV2Daytimer.js.map +0 -1
- package/build/controls/IRoomControllerV2.js +0 -371
- package/build/controls/IRoomControllerV2.js.map +0 -1
- package/build/controls/InfoOnlyAnalog.js +0 -38
- package/build/controls/InfoOnlyAnalog.js.map +0 -1
- package/build/controls/InfoOnlyDigital.js +0 -65
- package/build/controls/InfoOnlyDigital.js.map +0 -1
- package/build/controls/InfoOnlyText.js +0 -35
- package/build/controls/InfoOnlyText.js.map +0 -1
- package/build/controls/Intercom.js.map +0 -1
- package/build/controls/Jalousie.js +0 -153
- package/build/controls/Jalousie.js.map +0 -1
- package/build/controls/LightController.js +0 -68
- package/build/controls/LightController.js.map +0 -1
- package/build/controls/LightControllerV2.js +0 -195
- package/build/controls/LightControllerV2.js.map +0 -1
- package/build/controls/MailBox.js +0 -41
- package/build/controls/MailBox.js.map +0 -1
- package/build/controls/Meter.js +0 -52
- package/build/controls/Meter.js.map +0 -1
- package/build/controls/None.js +0 -23
- package/build/controls/None.js.map +0 -1
- package/build/controls/PresenceDetector.js +0 -29
- package/build/controls/PresenceDetector.js.map +0 -1
- package/build/controls/Pushbutton.js +0 -35
- package/build/controls/Pushbutton.js.map +0 -1
- package/build/controls/Radio.js +0 -39
- package/build/controls/Radio.js.map +0 -1
- package/build/controls/Remote.js.map +0 -1
- package/build/controls/Slider.js +0 -44
- package/build/controls/Slider.js.map +0 -1
- package/build/controls/SmokeAlarm.js +0 -85
- package/build/controls/SmokeAlarm.js.map +0 -1
- package/build/controls/Switch.js +0 -31
- package/build/controls/Switch.js.map +0 -1
- package/build/controls/SystemScheme.js +0 -11
- package/build/controls/SystemScheme.js.map +0 -1
- package/build/controls/TextInput.js +0 -55
- package/build/controls/TextInput.js.map +0 -1
- package/build/controls/TextState.js +0 -20
- package/build/controls/TextState.js.map +0 -1
- package/build/controls/TimedSwitch.js +0 -36
- package/build/controls/TimedSwitch.js.map +0 -1
- package/build/controls/Tracker.js +0 -20
- package/build/controls/Tracker.js.map +0 -1
- package/build/controls/Unknown.js.map +0 -1
- package/build/controls/UpDownAnalog.js +0 -44
- package/build/controls/UpDownAnalog.js.map +0 -1
- package/build/controls/ValueSelector.js.map +0 -1
- package/build/controls/WindowMonitor.js +0 -84
- package/build/controls/WindowMonitor.js.map +0 -1
- package/build/controls/control-base.js +0 -12
- package/build/controls/control-base.js.map +0 -1
- package/build/loxone-handler-base.js +0 -186
- package/build/loxone-handler-base.js.map +0 -1
- package/build/main.js.map +0 -1
- package/build/weather-server-handler.js +0 -120
- package/build/weather-server-handler.js.map +0 -1
- package/doc/details-missing-control-type.png +0 -0
- package/doc/log-missing-control-type.png +0 -0
- package/doc/loxone-config-display-diagnostics.png +0 -0
- package/doc/loxone-config-info-only-digital.png +0 -0
- package/doc/loxone-config-use-in-visualization.png +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Control } from '../structure-file';
|
|
2
|
+
import type { ControlType } from './control-base';
|
|
3
|
+
import { ControlBase } from './control-base';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Handler for InfoOnlyDigital controls.
|
|
7
|
+
*/
|
|
8
|
+
export class InfoOnlyDigital extends ControlBase {
|
|
9
|
+
/**
|
|
10
|
+
* Loads the control and sets up state objects and event handlers.
|
|
11
|
+
*
|
|
12
|
+
* @param type The type of the control ('device' or 'channel').
|
|
13
|
+
* @param uuid The unique identifier of the control.
|
|
14
|
+
* @param control The control data from the structure file.
|
|
15
|
+
*/
|
|
16
|
+
async loadAsync(type: ControlType, uuid: string, control: Control): Promise<void> {
|
|
17
|
+
await this.updateObjectAsync(uuid, {
|
|
18
|
+
type: type,
|
|
19
|
+
common: {
|
|
20
|
+
name: control.name,
|
|
21
|
+
role: 'switch',
|
|
22
|
+
},
|
|
23
|
+
native: { control },
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
await this.loadOtherControlStatesAsync(control.name, uuid, control.states, ['active']);
|
|
27
|
+
|
|
28
|
+
if (!('states' in control) || !('active' in control.states)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
await this.createBooleanControlStateObjectAsync(control.name, uuid, control.states, 'active', 'indicator');
|
|
33
|
+
|
|
34
|
+
if (!('details' in control)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if ('text' in control.details) {
|
|
39
|
+
const text: any = control.details.text;
|
|
40
|
+
await this.updateStateObjectAsync(
|
|
41
|
+
`${uuid}.active-text`,
|
|
42
|
+
{
|
|
43
|
+
name: `${control.name}: active as text`,
|
|
44
|
+
read: true,
|
|
45
|
+
write: false,
|
|
46
|
+
type: 'string',
|
|
47
|
+
role: 'text',
|
|
48
|
+
// TODO: re-add: smartIgnore: true,
|
|
49
|
+
},
|
|
50
|
+
control.states.active,
|
|
51
|
+
async (name: string, value: any) => {
|
|
52
|
+
await this.setStateAck(name, value == 1 ? text.on : text.off);
|
|
53
|
+
},
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if ('image' in control.details) {
|
|
58
|
+
const image: any = control.details.image;
|
|
59
|
+
await this.updateStateObjectAsync(
|
|
60
|
+
`${uuid}.active-image`,
|
|
61
|
+
{
|
|
62
|
+
name: `${control.name}: active as image`,
|
|
63
|
+
read: true,
|
|
64
|
+
write: false,
|
|
65
|
+
type: 'string',
|
|
66
|
+
role: 'text',
|
|
67
|
+
// TODO: re-add: smartIgnore: true,
|
|
68
|
+
},
|
|
69
|
+
control.states.active,
|
|
70
|
+
async (name: string, value: any) => {
|
|
71
|
+
await this.setStateAck(name, value == 1 ? image.on : image.off);
|
|
72
|
+
},
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if ('color' in control.details) {
|
|
77
|
+
const color: any = control.details.color;
|
|
78
|
+
await this.updateStateObjectAsync(
|
|
79
|
+
`${uuid}.active-color`,
|
|
80
|
+
{
|
|
81
|
+
name: `${control.name}: active as color`,
|
|
82
|
+
read: true,
|
|
83
|
+
write: false,
|
|
84
|
+
type: 'string',
|
|
85
|
+
role: 'text',
|
|
86
|
+
// TODO: re-add: smartIgnore: true,
|
|
87
|
+
},
|
|
88
|
+
control.states.active,
|
|
89
|
+
async (name: string, value: any) => {
|
|
90
|
+
await this.setStateAck(name, value == 1 ? color.on : color.off);
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Control } from '../structure-file';
|
|
2
|
+
import type { ControlType } from './control-base';
|
|
3
|
+
import { ControlBase } from './control-base';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Handler for InfoOnlyText controls.
|
|
7
|
+
*/
|
|
8
|
+
export class InfoOnlyText extends ControlBase {
|
|
9
|
+
/**
|
|
10
|
+
* Loads the control and sets up state objects and event handlers.
|
|
11
|
+
*
|
|
12
|
+
* @param type The type of the control ('device' or 'channel').
|
|
13
|
+
* @param uuid The unique identifier of the control.
|
|
14
|
+
* @param control The control data from the structure file.
|
|
15
|
+
*/
|
|
16
|
+
async loadAsync(type: ControlType, uuid: string, control: Control): Promise<void> {
|
|
17
|
+
await this.updateObjectAsync(uuid, {
|
|
18
|
+
type: type,
|
|
19
|
+
common: {
|
|
20
|
+
name: control.name,
|
|
21
|
+
role: 'info',
|
|
22
|
+
},
|
|
23
|
+
native: { control },
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
await this.loadOtherControlStatesAsync(control.name, uuid, control.states, ['text']);
|
|
27
|
+
|
|
28
|
+
await this.createSimpleControlStateObjectAsync(control.name, uuid, control.states, 'text', 'string', 'text');
|
|
29
|
+
|
|
30
|
+
if (!('details' in control)) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if ('format' in control.details) {
|
|
35
|
+
await this.updateStateObjectAsync(
|
|
36
|
+
`${uuid}.text-formatted`,
|
|
37
|
+
{
|
|
38
|
+
name: `${control.name}: formatted value`,
|
|
39
|
+
read: true,
|
|
40
|
+
write: false,
|
|
41
|
+
type: 'string',
|
|
42
|
+
role: 'text',
|
|
43
|
+
// TODO: re-add: smartIgnore: true,
|
|
44
|
+
},
|
|
45
|
+
control.states.value,
|
|
46
|
+
async (name: string, value: any) => {
|
|
47
|
+
await this.setFormattedStateAck(name, value, control.details.format as string);
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import type { Control } from '../structure-file';
|
|
2
|
+
import type { ControlType } from './control-base';
|
|
3
|
+
import { ControlBase } from './control-base';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Handler for Intercom controls.
|
|
7
|
+
*/
|
|
8
|
+
export class Intercom extends ControlBase {
|
|
9
|
+
/**
|
|
10
|
+
* Loads the control and sets up state objects and event handlers.
|
|
11
|
+
*
|
|
12
|
+
* @param type The type of the control ('device' or 'channel').
|
|
13
|
+
* @param uuid The unique identifier of the control.
|
|
14
|
+
* @param control The control data from the structure file.
|
|
15
|
+
*/
|
|
16
|
+
async loadAsync(type: ControlType, uuid: string, control: Control): Promise<void> {
|
|
7
17
|
await this.updateObjectAsync(uuid, {
|
|
8
18
|
type: type,
|
|
9
19
|
common: {
|
|
@@ -12,20 +22,26 @@ class Intercom extends control_base_1.ControlBase {
|
|
|
12
22
|
},
|
|
13
23
|
native: { control },
|
|
14
24
|
});
|
|
25
|
+
|
|
15
26
|
await this.loadOtherControlStatesAsync(control.name, uuid, control.states, [
|
|
16
27
|
'bell',
|
|
17
28
|
'lastBellEvents',
|
|
18
29
|
'version',
|
|
19
30
|
]);
|
|
31
|
+
|
|
20
32
|
await this.createBooleanControlStateObjectAsync(control.name, uuid, control.states, 'bell', 'indicator');
|
|
21
33
|
await this.createListControlStateObjectAsync(control.name, uuid, control.states, 'lastBellEvents');
|
|
22
34
|
await this.createSimpleControlStateObjectAsync(control.name, uuid, control.states, 'version', 'string', 'text');
|
|
35
|
+
|
|
23
36
|
await this.createButtonCommandStateObjectAsync(control.name, uuid, 'answer');
|
|
24
|
-
this.addStateChangeListener(
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
this.addStateChangeListener(
|
|
38
|
+
`${uuid}.answer`,
|
|
39
|
+
() => {
|
|
40
|
+
this.sendCommand(control.uuidAction, 'answer');
|
|
41
|
+
},
|
|
42
|
+
{ selfAck: true },
|
|
43
|
+
);
|
|
44
|
+
|
|
27
45
|
await this.loadSubControlsAsync(uuid, control);
|
|
28
46
|
}
|
|
29
47
|
}
|
|
30
|
-
exports.Intercom = Intercom;
|
|
31
|
-
//# sourceMappingURL=Intercom.js.map
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import type { CurrentStateValue, OldStateValue } from '../main';
|
|
2
|
+
import type { Control } from '../structure-file';
|
|
3
|
+
import type { ControlType } from './control-base';
|
|
4
|
+
import { ControlBase } from './control-base';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Handler for Jalousie controls.
|
|
8
|
+
*/
|
|
9
|
+
export class Jalousie extends ControlBase {
|
|
10
|
+
private positionTarget: number | undefined;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Loads the control and sets up state objects and event handlers.
|
|
14
|
+
*
|
|
15
|
+
* @param type The type of the control ('device' or 'channel').
|
|
16
|
+
* @param uuid The unique identifier of the control.
|
|
17
|
+
* @param control The control data from the structure file.
|
|
18
|
+
*/
|
|
19
|
+
async loadAsync(type: ControlType, uuid: string, control: Control): Promise<void> {
|
|
20
|
+
await this.updateObjectAsync(uuid, {
|
|
21
|
+
type: type,
|
|
22
|
+
common: {
|
|
23
|
+
name: control.name,
|
|
24
|
+
role: 'blind',
|
|
25
|
+
},
|
|
26
|
+
native: { control },
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
await this.loadOtherControlStatesAsync(control.name, uuid, control.states, [
|
|
30
|
+
'up',
|
|
31
|
+
'down',
|
|
32
|
+
'position',
|
|
33
|
+
'shadePosition',
|
|
34
|
+
'safetyActive',
|
|
35
|
+
'autoAllowed',
|
|
36
|
+
'autoActive',
|
|
37
|
+
'locked',
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
await this.createBooleanControlStateObjectAsync(control.name, uuid, control.states, 'up', 'indicator', {
|
|
41
|
+
write: true,
|
|
42
|
+
});
|
|
43
|
+
this.addStateEventHandler(control.states.up, () => this.upDownChangeHandler(), 'up');
|
|
44
|
+
|
|
45
|
+
await this.createBooleanControlStateObjectAsync(control.name, uuid, control.states, 'down', 'indicator', {
|
|
46
|
+
write: true,
|
|
47
|
+
});
|
|
48
|
+
this.addStateEventHandler(control.states.down, () => this.upDownChangeHandler(), 'down');
|
|
49
|
+
|
|
50
|
+
await this.createPercentageControlStateObjectAsync(
|
|
51
|
+
control.name,
|
|
52
|
+
uuid,
|
|
53
|
+
control.states,
|
|
54
|
+
'position',
|
|
55
|
+
'level.blind',
|
|
56
|
+
{
|
|
57
|
+
write: true,
|
|
58
|
+
// TODO: re-add: smartIgnore: false
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
await this.createPercentageControlStateObjectAsync(
|
|
63
|
+
control.name,
|
|
64
|
+
uuid,
|
|
65
|
+
control.states,
|
|
66
|
+
'shadePosition',
|
|
67
|
+
'level',
|
|
68
|
+
);
|
|
69
|
+
await this.createBooleanControlStateObjectAsync(
|
|
70
|
+
control.name,
|
|
71
|
+
uuid,
|
|
72
|
+
control.states,
|
|
73
|
+
'safetyActive',
|
|
74
|
+
'indicator',
|
|
75
|
+
);
|
|
76
|
+
await this.createBooleanControlStateObjectAsync(control.name, uuid, control.states, 'autoAllowed', 'indicator');
|
|
77
|
+
await this.createBooleanControlStateObjectAsync(control.name, uuid, control.states, 'autoActive', 'indicator', {
|
|
78
|
+
write: true,
|
|
79
|
+
});
|
|
80
|
+
await this.createBooleanControlStateObjectAsync(control.name, uuid, control.states, 'locked', 'indicator');
|
|
81
|
+
await this.createSimpleControlStateObjectAsync(
|
|
82
|
+
control.name,
|
|
83
|
+
uuid,
|
|
84
|
+
control.states,
|
|
85
|
+
'infoText',
|
|
86
|
+
'string',
|
|
87
|
+
'text',
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
this.addStateChangeListener(`${uuid}.up`, (oldValue: OldStateValue, newValue: CurrentStateValue) => {
|
|
91
|
+
if (newValue) {
|
|
92
|
+
this.sendCommand(control.uuidAction, 'up');
|
|
93
|
+
} else {
|
|
94
|
+
this.sendCommand(control.uuidAction, 'UpOff');
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
this.addStateChangeListener(`${uuid}.down`, (oldValue: OldStateValue, newValue: CurrentStateValue) => {
|
|
98
|
+
if (newValue) {
|
|
99
|
+
this.sendCommand(control.uuidAction, 'down');
|
|
100
|
+
} else {
|
|
101
|
+
this.sendCommand(control.uuidAction, 'DownOff');
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
this.addStateChangeListener(
|
|
105
|
+
`${uuid}.autoActive`,
|
|
106
|
+
(oldValue: OldStateValue, newValue: CurrentStateValue) => {
|
|
107
|
+
if (newValue) {
|
|
108
|
+
this.sendCommand(control.uuidAction, 'auto');
|
|
109
|
+
} else {
|
|
110
|
+
this.sendCommand(control.uuidAction, 'NoAuto');
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
{ notIfEqual: true },
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
// for Alexa support:
|
|
117
|
+
// ... but this is not really Alexa specific to be fair
|
|
118
|
+
if (control.states.position) {
|
|
119
|
+
this.addStateChangeListener(
|
|
120
|
+
`${uuid}.position`,
|
|
121
|
+
(oldValue: OldStateValue, newValue: CurrentStateValue) => {
|
|
122
|
+
if (typeof oldValue !== 'number' || typeof newValue !== 'number') {
|
|
123
|
+
// This should never happen due to convertToInt flag
|
|
124
|
+
this.adapter.log.error(`Jalousie position is not a number`);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (newValue === 100) {
|
|
129
|
+
this.sendCommand(control.uuidAction, 'FullDown');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (newValue === 0) {
|
|
133
|
+
this.sendCommand(control.uuidAction, 'FullUp');
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this.upDownAutoCommandHandled = false;
|
|
138
|
+
if (oldValue < newValue) {
|
|
139
|
+
this.positionTarget = (newValue - 5) / 100;
|
|
140
|
+
this.sendCommand(control.uuidAction, 'down');
|
|
141
|
+
} else {
|
|
142
|
+
// Negative here because we use -ve numbers to indicate movement up
|
|
143
|
+
this.positionTarget = -(newValue + 5) / 100;
|
|
144
|
+
this.sendCommand(control.uuidAction, 'up');
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{ notIfEqual: true, convertToInt: true, minInt: 0, maxInt: 100, ackTimeoutMs: 2500 },
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
this.addStateEventHandler(
|
|
151
|
+
control.states.position,
|
|
152
|
+
(value: any) => {
|
|
153
|
+
if (typeof this.positionTarget === 'number') {
|
|
154
|
+
// Below, the actual command ('up' or 'down') is irrelevant but we
|
|
155
|
+
// need to know the direction for target test.
|
|
156
|
+
if (this.positionTarget > 0) {
|
|
157
|
+
// Going down
|
|
158
|
+
if (value >= this.positionTarget) {
|
|
159
|
+
this.positionTarget = undefined;
|
|
160
|
+
this.sendCommand(control.uuidAction, 'down');
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
// Going up - don't forget target is negative
|
|
164
|
+
if (value <= -this.positionTarget) {
|
|
165
|
+
this.positionTarget = undefined;
|
|
166
|
+
this.sendCommand(control.uuidAction, 'up');
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
'auto',
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
await this.createButtonCommandStateObjectAsync(control.name, uuid, 'fullUp');
|
|
176
|
+
this.addStateChangeListener(
|
|
177
|
+
`${uuid}.fullUp`,
|
|
178
|
+
() => {
|
|
179
|
+
this.sendCommand(control.uuidAction, 'FullUp');
|
|
180
|
+
},
|
|
181
|
+
{ selfAck: true },
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
await this.createButtonCommandStateObjectAsync(control.name, uuid, 'fullDown');
|
|
185
|
+
this.addStateChangeListener(
|
|
186
|
+
`${uuid}.fullDown`,
|
|
187
|
+
() => {
|
|
188
|
+
this.sendCommand(control.uuidAction, 'FullDown');
|
|
189
|
+
},
|
|
190
|
+
{ selfAck: true },
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
await this.createButtonCommandStateObjectAsync(control.name, uuid, 'shade');
|
|
194
|
+
this.addStateChangeListener(
|
|
195
|
+
`${uuid}.shade`,
|
|
196
|
+
() => {
|
|
197
|
+
this.sendCommand(control.uuidAction, 'shade');
|
|
198
|
+
},
|
|
199
|
+
{ selfAck: true },
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// The upDownChangeHandler callback will be triggered when any movement starts or stops.
|
|
204
|
+
// Normally we want upDownChangeHandler to clear any target as it signifies manual command
|
|
205
|
+
// has occurred. This can happen in normal use or before a target has been reached for
|
|
206
|
+
// example.
|
|
207
|
+
// But in the case of movement started as a result of an auto-position command, we don't
|
|
208
|
+
// want to clear that target.
|
|
209
|
+
// For this reason we have the below boolean that tells upDownChangeHandler to ignore the
|
|
210
|
+
// first change it sees after an auto-position command is started.
|
|
211
|
+
private upDownAutoCommandHandled = false;
|
|
212
|
+
private upDownChangeHandler(): void {
|
|
213
|
+
if (this.upDownAutoCommandHandled) {
|
|
214
|
+
this.positionTarget = undefined;
|
|
215
|
+
} else {
|
|
216
|
+
this.upDownAutoCommandHandled = true;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { CurrentStateValue, OldStateValue } from '../main';
|
|
2
|
+
import type { Control } from '../structure-file';
|
|
3
|
+
import type { ControlType } from './control-base';
|
|
4
|
+
import { ControlBase } from './control-base';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Handler for LightController controls.
|
|
8
|
+
*/
|
|
9
|
+
export class LightController extends ControlBase {
|
|
10
|
+
/**
|
|
11
|
+
* Loads the control and sets up state objects and event handlers.
|
|
12
|
+
*
|
|
13
|
+
* @param type The type of the control ('device' or 'channel').
|
|
14
|
+
* @param uuid The unique identifier of the control.
|
|
15
|
+
* @param control The control data from the structure file.
|
|
16
|
+
*/
|
|
17
|
+
async loadAsync(type: ControlType, uuid: string, control: Control): Promise<void> {
|
|
18
|
+
await this.updateObjectAsync(uuid, {
|
|
19
|
+
type: type,
|
|
20
|
+
common: {
|
|
21
|
+
name: control.name,
|
|
22
|
+
role: 'light',
|
|
23
|
+
},
|
|
24
|
+
native: { control },
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
await this.loadOtherControlStatesAsync(control.name, uuid, control.states, ['activeScene', 'sceneList']);
|
|
28
|
+
|
|
29
|
+
await this.createSimpleControlStateObjectAsync(
|
|
30
|
+
control.name,
|
|
31
|
+
uuid,
|
|
32
|
+
control.states,
|
|
33
|
+
'activeScene',
|
|
34
|
+
'number',
|
|
35
|
+
'level',
|
|
36
|
+
{ write: true },
|
|
37
|
+
);
|
|
38
|
+
this.addStateChangeListener(`${uuid}.activeScene`, (oldValue: OldStateValue, newValue: CurrentStateValue) => {
|
|
39
|
+
newValue = this.convertStateToInt(newValue);
|
|
40
|
+
if (newValue === 9) {
|
|
41
|
+
this.sendCommand(control.uuidAction, 'on');
|
|
42
|
+
} else {
|
|
43
|
+
this.sendCommand(control.uuidAction, newValue.toString());
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if ('sceneList' in control.states) {
|
|
48
|
+
await this.updateStateObjectAsync(
|
|
49
|
+
`${uuid}.sceneList`,
|
|
50
|
+
{
|
|
51
|
+
name: `${control.name}: sceneList`,
|
|
52
|
+
read: true,
|
|
53
|
+
write: false,
|
|
54
|
+
type: 'array',
|
|
55
|
+
role: 'list',
|
|
56
|
+
// TODO: re-add: smartIgnore: true,
|
|
57
|
+
},
|
|
58
|
+
control.states.sceneList,
|
|
59
|
+
async (name: string, value: any) => {
|
|
60
|
+
// weird documentation: they say it's 'text' within the struct, but I get the value directly; let's support both
|
|
61
|
+
if ('text' in value) {
|
|
62
|
+
await this.setStateAck(name, value.text.split(','));
|
|
63
|
+
} else {
|
|
64
|
+
await this.setStateAck(name, value.toString().split(','));
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
await this.createButtonCommandStateObjectAsync(control.name, uuid, 'plus');
|
|
71
|
+
this.addStateChangeListener(
|
|
72
|
+
`${uuid}.plus`,
|
|
73
|
+
() => {
|
|
74
|
+
this.sendCommand(control.uuidAction, 'plus');
|
|
75
|
+
},
|
|
76
|
+
{ selfAck: true },
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
await this.createButtonCommandStateObjectAsync(control.name, uuid, 'minus');
|
|
80
|
+
this.addStateChangeListener(
|
|
81
|
+
`${uuid}.minus`,
|
|
82
|
+
() => {
|
|
83
|
+
this.sendCommand(control.uuidAction, 'minus');
|
|
84
|
+
},
|
|
85
|
+
{ selfAck: true },
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// for Alexa support:
|
|
89
|
+
await this.createButtonCommandStateObjectAsync(
|
|
90
|
+
control.name,
|
|
91
|
+
uuid,
|
|
92
|
+
'control',
|
|
93
|
+
/* TODO: re-add: { smartIgnore: false }*/
|
|
94
|
+
);
|
|
95
|
+
this.addStateChangeListener(
|
|
96
|
+
`${uuid}.control`,
|
|
97
|
+
(oldValue: OldStateValue, newValue: CurrentStateValue) => {
|
|
98
|
+
if (newValue) {
|
|
99
|
+
this.sendCommand(control.uuidAction, 'on');
|
|
100
|
+
} else {
|
|
101
|
+
this.sendCommand(control.uuidAction, '0');
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
{ selfAck: true },
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// TODO: currently we don't support scene modifications ("learn" and "delete" commands),
|
|
108
|
+
// IMHO this should be done by the user through the Loxone Web interface
|
|
109
|
+
|
|
110
|
+
await this.loadSubControlsAsync(uuid, control);
|
|
111
|
+
}
|
|
112
|
+
}
|