iobroker.loxone 3.0.1 → 4.0.1
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 +421 -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 +60 -49
- 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} +516 -310
- 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
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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 ValueSelector controls.
|
|
8
|
+
*/
|
|
9
|
+
export class ValueSelector 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> {
|
|
7
18
|
await this.updateObjectAsync(uuid, {
|
|
8
19
|
type: type,
|
|
9
20
|
common: {
|
|
@@ -12,17 +23,18 @@ class ValueSelector extends control_base_1.ControlBase {
|
|
|
12
23
|
},
|
|
13
24
|
native: { control },
|
|
14
25
|
});
|
|
26
|
+
|
|
15
27
|
await this.loadOtherControlStatesAsync(control.name, uuid, control.states, ['value', 'min', 'max', 'step']);
|
|
28
|
+
|
|
16
29
|
await this.createSimpleControlStateObjectAsync(control.name, uuid, control.states, 'value', 'number', 'level', {
|
|
17
30
|
write: true,
|
|
18
31
|
});
|
|
19
32
|
await this.createSimpleControlStateObjectAsync(control.name, uuid, control.states, 'min', 'number', 'value');
|
|
20
33
|
await this.createSimpleControlStateObjectAsync(control.name, uuid, control.states, 'max', 'number', 'value');
|
|
21
34
|
await this.createSimpleControlStateObjectAsync(control.name, uuid, control.states, 'step', 'number', 'value');
|
|
22
|
-
|
|
35
|
+
|
|
36
|
+
this.addStateChangeListener(`${uuid}.value`, (oldValue: OldStateValue, newValue: CurrentStateValue) => {
|
|
23
37
|
this.sendCommand(control.uuidAction, this.convertStateToInt(newValue).toString());
|
|
24
38
|
});
|
|
25
39
|
}
|
|
26
40
|
}
|
|
27
|
-
exports.ValueSelector = ValueSelector;
|
|
28
|
-
//# sourceMappingURL=ValueSelector.js.map
|
|
@@ -0,0 +1,139 @@
|
|
|
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 WindowMonitor controls.
|
|
7
|
+
*/
|
|
8
|
+
export class WindowMonitor 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: 'sensor',
|
|
22
|
+
},
|
|
23
|
+
native: { control },
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
await this.loadOtherControlStatesAsync(control.name, uuid, control.states, [
|
|
27
|
+
'windowStates',
|
|
28
|
+
'numOpen',
|
|
29
|
+
'numClosed',
|
|
30
|
+
'numTilted',
|
|
31
|
+
'numOffline',
|
|
32
|
+
'numLocked',
|
|
33
|
+
'numUnlocked',
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
await this.createSimpleControlStateObjectAsync(
|
|
37
|
+
control.name,
|
|
38
|
+
uuid,
|
|
39
|
+
control.states,
|
|
40
|
+
'numOpen',
|
|
41
|
+
'number',
|
|
42
|
+
'value',
|
|
43
|
+
);
|
|
44
|
+
await this.createSimpleControlStateObjectAsync(
|
|
45
|
+
control.name,
|
|
46
|
+
uuid,
|
|
47
|
+
control.states,
|
|
48
|
+
'numClosed',
|
|
49
|
+
'number',
|
|
50
|
+
'value',
|
|
51
|
+
);
|
|
52
|
+
await this.createSimpleControlStateObjectAsync(
|
|
53
|
+
control.name,
|
|
54
|
+
uuid,
|
|
55
|
+
control.states,
|
|
56
|
+
'numTilted',
|
|
57
|
+
'number',
|
|
58
|
+
'value',
|
|
59
|
+
);
|
|
60
|
+
await this.createSimpleControlStateObjectAsync(
|
|
61
|
+
control.name,
|
|
62
|
+
uuid,
|
|
63
|
+
control.states,
|
|
64
|
+
'numOffline',
|
|
65
|
+
'number',
|
|
66
|
+
'value',
|
|
67
|
+
);
|
|
68
|
+
await this.createSimpleControlStateObjectAsync(
|
|
69
|
+
control.name,
|
|
70
|
+
uuid,
|
|
71
|
+
control.states,
|
|
72
|
+
'numLocked',
|
|
73
|
+
'number',
|
|
74
|
+
'value',
|
|
75
|
+
);
|
|
76
|
+
await this.createSimpleControlStateObjectAsync(
|
|
77
|
+
control.name,
|
|
78
|
+
uuid,
|
|
79
|
+
control.states,
|
|
80
|
+
'numUnlocked',
|
|
81
|
+
'number',
|
|
82
|
+
'value',
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
if (!('details' in control) || !('windows' in control.details) || !('windowStates' in control.states)) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const windowPositions: Record<number, string> = {
|
|
89
|
+
1: 'closed',
|
|
90
|
+
2: 'tilted',
|
|
91
|
+
4: 'open',
|
|
92
|
+
8: 'locked',
|
|
93
|
+
16: 'unlocked',
|
|
94
|
+
};
|
|
95
|
+
const windows = control.details.windows as any;
|
|
96
|
+
for (const index in windows) {
|
|
97
|
+
const window = windows[index];
|
|
98
|
+
const id = `${uuid}.${parseInt(index) + 1}`;
|
|
99
|
+
await this.updateObjectAsync(id, {
|
|
100
|
+
type: 'channel',
|
|
101
|
+
common: {
|
|
102
|
+
name: `${control.name}: ${window.name}`,
|
|
103
|
+
role: 'sensor.window.3',
|
|
104
|
+
// TODO: re-add: smartIgnore: true,
|
|
105
|
+
},
|
|
106
|
+
native: window,
|
|
107
|
+
});
|
|
108
|
+
for (let mask = 1; mask <= 16; mask *= 2) {
|
|
109
|
+
const windowPosition = windowPositions[mask];
|
|
110
|
+
const obj: ioBroker.SettableObject = {
|
|
111
|
+
type: 'state',
|
|
112
|
+
common: {
|
|
113
|
+
name: `${control.name}: ${window.name}: ${windowPosition}`,
|
|
114
|
+
read: true,
|
|
115
|
+
write: false,
|
|
116
|
+
type: 'boolean',
|
|
117
|
+
role: 'indicator',
|
|
118
|
+
// TODO: re-add: smartIgnore: true,
|
|
119
|
+
},
|
|
120
|
+
native: {},
|
|
121
|
+
};
|
|
122
|
+
await this.updateObjectAsync(`${id}.${windowPosition}`, obj);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.addStateEventHandler(control.states.windowStates, async (value: any) => {
|
|
127
|
+
const values = value.toString().split(',');
|
|
128
|
+
for (const index in values) {
|
|
129
|
+
for (let mask = 1; mask <= 16; mask *= 2) {
|
|
130
|
+
const windowPosition = windowPositions[mask];
|
|
131
|
+
await this.setStateAck(
|
|
132
|
+
`${uuid}.${parseInt(index) + 1}.${windowPosition}`,
|
|
133
|
+
(parseInt(values[index]) & mask) == mask,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { AalEmergency } from './AalEmergency';
|
|
2
|
+
import { AalSmartAlarm } from './AalSmartAlarm';
|
|
3
|
+
import { Alarm } from './Alarm';
|
|
4
|
+
import { AlarmClock } from './AlarmClock';
|
|
5
|
+
import { Application } from './Application';
|
|
6
|
+
import { AudioZone } from './AudioZone';
|
|
7
|
+
import { AudioZoneV2 } from './AudioZoneV2';
|
|
8
|
+
import { CentralAlarm } from './CentralAlarm';
|
|
9
|
+
import { CentralAudioZone } from './CentralAudioZone';
|
|
10
|
+
import { CentralGate } from './CentralGate';
|
|
11
|
+
import { CentralJalousie } from './CentralJalousie';
|
|
12
|
+
import { CentralLightController } from './CentralLightController';
|
|
13
|
+
import { Colorpicker } from './Colorpicker';
|
|
14
|
+
import { ColorPickerV2 } from './ColorPickerV2';
|
|
15
|
+
import { Daytimer } from './Daytimer';
|
|
16
|
+
import { Dimmer } from './Dimmer';
|
|
17
|
+
import { EIBDimmer } from './EIBDimmer';
|
|
18
|
+
import { Fronius } from './Fronius';
|
|
19
|
+
import { Gate } from './Gate';
|
|
20
|
+
import { Hourcounter } from './Hourcounter';
|
|
21
|
+
import { InfoOnlyAnalog } from './InfoOnlyAnalog';
|
|
22
|
+
import { InfoOnlyDigital } from './InfoOnlyDigital';
|
|
23
|
+
import { InfoOnlyText } from './InfoOnlyText';
|
|
24
|
+
import { Intercom } from './Intercom';
|
|
25
|
+
import { IRCDaytimer } from './IRCDaytimer';
|
|
26
|
+
import { IRCV2Daytimer } from './IRCV2Daytimer';
|
|
27
|
+
import { IRoomControllerV2 } from './IRoomControllerV2';
|
|
28
|
+
import { Jalousie } from './Jalousie';
|
|
29
|
+
import { LightController } from './LightController';
|
|
30
|
+
import { LightControllerV2 } from './LightControllerV2';
|
|
31
|
+
import { MailBox } from './MailBox';
|
|
32
|
+
import { Meter } from './Meter';
|
|
33
|
+
import { PresenceDetector } from './PresenceDetector';
|
|
34
|
+
import { Pushbutton } from './Pushbutton';
|
|
35
|
+
import { Radio } from './Radio';
|
|
36
|
+
import { Remote } from './Remote';
|
|
37
|
+
import { Slider } from './Slider';
|
|
38
|
+
import { SmokeAlarm } from './SmokeAlarm';
|
|
39
|
+
import { Switch } from './Switch';
|
|
40
|
+
import { SystemScheme } from './SystemScheme';
|
|
41
|
+
import { TextInput } from './TextInput';
|
|
42
|
+
import { TextState } from './TextState';
|
|
43
|
+
import { TimedSwitch } from './TimedSwitch';
|
|
44
|
+
import { Tracker } from './Tracker';
|
|
45
|
+
import { Unknown } from './Unknown';
|
|
46
|
+
import { UpDownAnalog } from './UpDownAnalog';
|
|
47
|
+
import { ValueSelector } from './ValueSelector';
|
|
48
|
+
import { WindowMonitor } from './WindowMonitor';
|
|
49
|
+
|
|
50
|
+
export const AllControls = {
|
|
51
|
+
AalEmergency,
|
|
52
|
+
AalSmartAlarm,
|
|
53
|
+
AlarmClock,
|
|
54
|
+
Alarm,
|
|
55
|
+
Application,
|
|
56
|
+
AudioZone,
|
|
57
|
+
AudioZoneV2,
|
|
58
|
+
CentralAlarm,
|
|
59
|
+
CentralAudioZone,
|
|
60
|
+
CentralGate,
|
|
61
|
+
CentralJalousie,
|
|
62
|
+
CentralLightController,
|
|
63
|
+
Colorpicker,
|
|
64
|
+
ColorPickerV2,
|
|
65
|
+
Daytimer,
|
|
66
|
+
Dimmer,
|
|
67
|
+
EIBDimmer,
|
|
68
|
+
Fronius,
|
|
69
|
+
Gate,
|
|
70
|
+
Hourcounter,
|
|
71
|
+
InfoOnlyAnalog,
|
|
72
|
+
InfoOnlyDigital,
|
|
73
|
+
InfoOnlyText,
|
|
74
|
+
Intercom,
|
|
75
|
+
IRCDaytimer,
|
|
76
|
+
IRCV2Daytimer,
|
|
77
|
+
IRoomControllerV2,
|
|
78
|
+
Jalousie,
|
|
79
|
+
LightController,
|
|
80
|
+
LightControllerV2,
|
|
81
|
+
MailBox,
|
|
82
|
+
Meter,
|
|
83
|
+
PresenceDetector,
|
|
84
|
+
Pushbutton,
|
|
85
|
+
Radio,
|
|
86
|
+
Remote,
|
|
87
|
+
Slider,
|
|
88
|
+
SmokeAlarm,
|
|
89
|
+
Switch,
|
|
90
|
+
SystemScheme,
|
|
91
|
+
TextInput,
|
|
92
|
+
TextState,
|
|
93
|
+
TimedSwitch,
|
|
94
|
+
Tracker,
|
|
95
|
+
Unknown,
|
|
96
|
+
UpDownAnalog,
|
|
97
|
+
ValueSelector,
|
|
98
|
+
WindowMonitor,
|
|
99
|
+
} as const;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { LoxoneHandlerBase } from '../loxone-handler-base';
|
|
2
|
+
import type { Loxone } from '../main';
|
|
3
|
+
import type { Control } from '../structure-file';
|
|
4
|
+
|
|
5
|
+
export type ControlType = 'device' | 'channel';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Base class for all control handlers.
|
|
9
|
+
*/
|
|
10
|
+
export abstract class ControlBase extends LoxoneHandlerBase {
|
|
11
|
+
/**
|
|
12
|
+
* Creates an instance of this class.
|
|
13
|
+
*
|
|
14
|
+
* @param adapter The Loxone adapter instance.
|
|
15
|
+
*/
|
|
16
|
+
constructor(protected readonly adapter: Loxone) {
|
|
17
|
+
super(adapter);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Loads the control and sets up state objects and event handlers.
|
|
22
|
+
*
|
|
23
|
+
* @param type The type of the control ('device' or 'channel').
|
|
24
|
+
* @param uuid The unique identifier of the control.
|
|
25
|
+
* @param control The control data from the structure file.
|
|
26
|
+
*/
|
|
27
|
+
abstract loadAsync(type: ControlType, uuid: string, control: Control): Promise<void>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// This file extends the AdapterConfig type from "@iobroker/types"
|
|
2
|
+
|
|
3
|
+
// Augment the globally declared type ioBroker.AdapterConfig
|
|
4
|
+
declare global {
|
|
5
|
+
namespace ioBroker {
|
|
6
|
+
interface AdapterConfig {
|
|
7
|
+
host: string;
|
|
8
|
+
port: number;
|
|
9
|
+
username: string;
|
|
10
|
+
password: string;
|
|
11
|
+
syncNames: boolean;
|
|
12
|
+
syncRooms: boolean;
|
|
13
|
+
syncFunctions: boolean;
|
|
14
|
+
|
|
15
|
+
/** if not set, it implies "all" */
|
|
16
|
+
weatherServer?: 'off' | 'current' | '1day' | 'all';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// this is required so the above AdapterConfig is found by TypeScript / type checking
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { sprintf } from 'sprintf-js';
|
|
2
|
+
import type {
|
|
3
|
+
CurrentStateValue,
|
|
4
|
+
Loxone,
|
|
5
|
+
NamedStateEventHandler,
|
|
6
|
+
OldStateValue,
|
|
7
|
+
StateChangeListener,
|
|
8
|
+
StateChangeListenerOpts,
|
|
9
|
+
StateEventHandler,
|
|
10
|
+
} from './main';
|
|
11
|
+
import type { Control, ControlStates } from './structure-file';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Base class for Loxone handlers.
|
|
15
|
+
*/
|
|
16
|
+
export abstract class LoxoneHandlerBase {
|
|
17
|
+
protected constructor(protected readonly adapter: Loxone) {}
|
|
18
|
+
|
|
19
|
+
protected async loadSubControlsAsync(parentUuid: string, control: Control): Promise<void> {
|
|
20
|
+
return await this.adapter.loadSubControlsAsync(parentUuid, control);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
protected addStateChangeListener(id: string, listener: StateChangeListener, opts?: StateChangeListenerOpts): void {
|
|
24
|
+
this.adapter.addStateChangeListener(id, listener, opts);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
protected addStateEventHandler(uuid: string, eventHandler: StateEventHandler, name?: string): void {
|
|
28
|
+
this.adapter.addStateEventHandler(uuid, eventHandler, name);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
protected removeStateEventHandler(uuid: string, name: string): boolean {
|
|
32
|
+
return this.adapter.removeStateEventHandler(uuid, name);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
protected sendCommand(uuid: string, action: string): void {
|
|
36
|
+
this.adapter.sendCommand(uuid, action);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
protected async setStateAck(id: string, value: CurrentStateValue): Promise<void> {
|
|
40
|
+
await this.adapter.setStateAck(id, value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
protected async setFormattedStateAck(id: string, value: CurrentStateValue, format: string): Promise<void> {
|
|
44
|
+
value = sprintf(format, value);
|
|
45
|
+
await this.setStateAck(id, value);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected convertStateToInt(value: OldStateValue): number {
|
|
49
|
+
return this.adapter.convertStateToInt(value);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
protected convertStateToFloat(value: OldStateValue): number {
|
|
53
|
+
if (typeof value === 'number') {
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
return !value ? 0 : parseFloat(value.toString());
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
protected convertStateToBoolean(value: OldStateValue): boolean {
|
|
60
|
+
if (!value) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
if (typeof value === 'boolean') {
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
value = value.toString();
|
|
67
|
+
return value !== '0' && value !== 'false';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
protected getCachedStateValue(id: string): OldStateValue {
|
|
71
|
+
return this.adapter.getCachedStateValue(id);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
protected async updateObjectAsync(id: string, obj: ioBroker.SettableObject): Promise<void> {
|
|
75
|
+
await this.adapter.updateObjectAsync(id, obj);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
protected async updateStateObjectAsync(
|
|
79
|
+
id: string,
|
|
80
|
+
commonInfo: ioBroker.StateCommon,
|
|
81
|
+
stateUuid: string,
|
|
82
|
+
stateEventHandler?: NamedStateEventHandler,
|
|
83
|
+
): Promise<void> {
|
|
84
|
+
await this.adapter.updateStateObjectAsync(id, commonInfo, stateUuid, stateEventHandler);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
protected async loadOtherControlStatesAsync(
|
|
88
|
+
controlName: string,
|
|
89
|
+
uuid: string,
|
|
90
|
+
states: ControlStates,
|
|
91
|
+
skipKeys: string[],
|
|
92
|
+
): Promise<void> {
|
|
93
|
+
if (states === undefined) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (const stateName in states) {
|
|
98
|
+
if (skipKeys.indexOf(stateName) !== -1) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
await this.createSimpleControlStateObjectAsync(controlName, uuid, states, stateName, 'string', 'text', {
|
|
103
|
+
desc: 'This state is currently unsupported by this adapter, you can only see the text representation of it.',
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
protected async createSimpleControlStateObjectAsync(
|
|
109
|
+
controlName: string,
|
|
110
|
+
uuid: string,
|
|
111
|
+
states: ControlStates,
|
|
112
|
+
name: string,
|
|
113
|
+
type: ioBroker.CommonType,
|
|
114
|
+
role: string,
|
|
115
|
+
commonExt?: Partial<ioBroker.StateCommon>,
|
|
116
|
+
): Promise<void> {
|
|
117
|
+
if (states !== undefined && name in states) {
|
|
118
|
+
let common: ioBroker.StateCommon = {
|
|
119
|
+
name: `${controlName}: ${name}`,
|
|
120
|
+
read: true,
|
|
121
|
+
write: false,
|
|
122
|
+
type: type,
|
|
123
|
+
role: role,
|
|
124
|
+
// TODO: re-add: smartIgnore: true,
|
|
125
|
+
};
|
|
126
|
+
if (commonExt && typeof commonExt === 'object') {
|
|
127
|
+
common = { ...common, ...commonExt };
|
|
128
|
+
}
|
|
129
|
+
await this.updateStateObjectAsync(
|
|
130
|
+
`${uuid}.${this.normalizeName(name)}`,
|
|
131
|
+
common,
|
|
132
|
+
states[name],
|
|
133
|
+
(id, value) => {
|
|
134
|
+
switch (type) {
|
|
135
|
+
case 'number':
|
|
136
|
+
value = this.convertStateToFloat(value);
|
|
137
|
+
break;
|
|
138
|
+
case 'boolean':
|
|
139
|
+
value = this.convertStateToBoolean(value);
|
|
140
|
+
break;
|
|
141
|
+
default:
|
|
142
|
+
value = value === null || value === undefined ? '' : value.toString();
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
return this.setStateAck(id, value);
|
|
146
|
+
},
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
protected async createBooleanControlStateObjectAsync(
|
|
152
|
+
controlName: string,
|
|
153
|
+
uuid: string,
|
|
154
|
+
states: ControlStates,
|
|
155
|
+
name: string,
|
|
156
|
+
role: string,
|
|
157
|
+
commonExt?: Partial<ioBroker.StateCommon>,
|
|
158
|
+
converter?: (value: CurrentStateValue) => boolean,
|
|
159
|
+
): Promise<void> {
|
|
160
|
+
if (states !== undefined && name in states) {
|
|
161
|
+
let common: ioBroker.StateCommon = {
|
|
162
|
+
name: `${controlName}: ${name}`,
|
|
163
|
+
read: true,
|
|
164
|
+
write: false,
|
|
165
|
+
type: 'boolean' as ioBroker.CommonType,
|
|
166
|
+
role: role,
|
|
167
|
+
// TODO: re-add: smartIgnore: true,
|
|
168
|
+
};
|
|
169
|
+
if (commonExt && typeof commonExt === 'object') {
|
|
170
|
+
common = { ...common, ...commonExt };
|
|
171
|
+
}
|
|
172
|
+
const convert = converter || (value => value == 1);
|
|
173
|
+
await this.updateStateObjectAsync(
|
|
174
|
+
`${uuid}.${this.normalizeName(name)}`,
|
|
175
|
+
common,
|
|
176
|
+
states[name],
|
|
177
|
+
async (name: string, value: CurrentStateValue) => {
|
|
178
|
+
await this.setStateAck(name, convert(value));
|
|
179
|
+
},
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
protected async createListControlStateObjectAsync(
|
|
185
|
+
controlName: string,
|
|
186
|
+
uuid: string,
|
|
187
|
+
states: ControlStates,
|
|
188
|
+
name: string,
|
|
189
|
+
): Promise<void> {
|
|
190
|
+
if (states !== undefined && name in states) {
|
|
191
|
+
await this.updateStateObjectAsync(
|
|
192
|
+
`${uuid}.${this.normalizeName(name)}`,
|
|
193
|
+
{
|
|
194
|
+
name: `${controlName}: ${name}`,
|
|
195
|
+
read: true,
|
|
196
|
+
write: false,
|
|
197
|
+
type: 'array',
|
|
198
|
+
role: 'list',
|
|
199
|
+
// TODO: re-add: smartIgnore: true,
|
|
200
|
+
},
|
|
201
|
+
states[name],
|
|
202
|
+
async (name: string, value: CurrentStateValue) => {
|
|
203
|
+
await this.setStateAck(name, !value ? '[]' : JSON.stringify(value.toString().split('|')));
|
|
204
|
+
},
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
protected async createPercentageControlStateObjectAsync(
|
|
210
|
+
controlName: string,
|
|
211
|
+
uuid: string,
|
|
212
|
+
states: ControlStates,
|
|
213
|
+
name: string,
|
|
214
|
+
role: string,
|
|
215
|
+
commonExt?: Partial<ioBroker.StateCommon>,
|
|
216
|
+
): Promise<void> {
|
|
217
|
+
if (states !== undefined && name in states) {
|
|
218
|
+
let common: ioBroker.StateCommon = {
|
|
219
|
+
name: `${controlName}: ${name}`,
|
|
220
|
+
read: true,
|
|
221
|
+
write: false,
|
|
222
|
+
type: 'number' as ioBroker.CommonType,
|
|
223
|
+
role: role,
|
|
224
|
+
unit: '%',
|
|
225
|
+
// TODO: re-add: smartIgnore: true,
|
|
226
|
+
};
|
|
227
|
+
if (commonExt && typeof commonExt === 'object') {
|
|
228
|
+
common = { ...common, ...commonExt };
|
|
229
|
+
}
|
|
230
|
+
await this.updateStateObjectAsync(
|
|
231
|
+
`${uuid}.${this.normalizeName(name)}`,
|
|
232
|
+
common,
|
|
233
|
+
states[name],
|
|
234
|
+
async (name: string, value: CurrentStateValue) => {
|
|
235
|
+
await this.setStateAck(name, Math.round(this.convertStateToFloat(value) * 100));
|
|
236
|
+
},
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
protected async createButtonCommandStateObjectAsync(
|
|
242
|
+
controlName: string,
|
|
243
|
+
uuid: string,
|
|
244
|
+
name: string,
|
|
245
|
+
commonExt?: Partial<ioBroker.StateCommon>,
|
|
246
|
+
): Promise<void> {
|
|
247
|
+
let common: ioBroker.StateCommon = {
|
|
248
|
+
name: `${controlName}: ${name}`,
|
|
249
|
+
read: false,
|
|
250
|
+
write: true,
|
|
251
|
+
type: 'boolean',
|
|
252
|
+
role: 'button',
|
|
253
|
+
// TODO: re-add: smartIgnore: true,
|
|
254
|
+
};
|
|
255
|
+
if (commonExt && typeof commonExt === 'object') {
|
|
256
|
+
common = { ...common, ...commonExt };
|
|
257
|
+
}
|
|
258
|
+
await this.updateStateObjectAsync(`${uuid}.${this.normalizeName(name)}`, common, uuid);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
protected async createNumberInputStateObjectAsync(
|
|
262
|
+
controlName: string,
|
|
263
|
+
uuid: string,
|
|
264
|
+
name: string,
|
|
265
|
+
role: string,
|
|
266
|
+
commonExt?: Partial<ioBroker.StateCommon>,
|
|
267
|
+
): Promise<void> {
|
|
268
|
+
let common: ioBroker.StateCommon = {
|
|
269
|
+
name: `${controlName}: ${name}`,
|
|
270
|
+
read: false,
|
|
271
|
+
write: true,
|
|
272
|
+
type: 'number',
|
|
273
|
+
role: role,
|
|
274
|
+
// TODO: re-add: smartIgnore: true,
|
|
275
|
+
};
|
|
276
|
+
if (commonExt && typeof commonExt === 'object') {
|
|
277
|
+
common = { ...common, ...commonExt };
|
|
278
|
+
}
|
|
279
|
+
await this.updateStateObjectAsync(`${uuid}.${this.normalizeName(name)}`, common, uuid);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
protected normalizeName(name: string): string {
|
|
283
|
+
return name.trim().replace(/[^\wäöüÄÖÜäöüéàèêçß]+/g, '_');
|
|
284
|
+
}
|
|
285
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module 'lxcommunicator';
|
package/src/main.test.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is a dummy TypeScript test file using chai and mocha
|
|
3
|
+
*
|
|
4
|
+
* It's automatically excluded from npm and its build output is excluded from both git and npm.
|
|
5
|
+
* It is advised to test all your modules with accompanying *.test.ts-files
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { expect } from 'chai';
|
|
9
|
+
// import { functionToTest } from "./moduleToTest";
|
|
10
|
+
|
|
11
|
+
describe('module to test => function to test', () => {
|
|
12
|
+
// initializing logic
|
|
13
|
+
const expected = 5;
|
|
14
|
+
|
|
15
|
+
it(`should return ${expected}`, () => {
|
|
16
|
+
const result = 5;
|
|
17
|
+
// assign result a value from functionToTest
|
|
18
|
+
expect(result).to.equal(expected);
|
|
19
|
+
// or using the should() syntax
|
|
20
|
+
result.should.equal(expected);
|
|
21
|
+
});
|
|
22
|
+
// ... more tests => it
|
|
23
|
+
});
|
|
24
|
+
// ... more test suites => describe
|