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.
Files changed (185) hide show
  1. package/LICENSE +183 -183
  2. package/README.md +421 -411
  3. package/admin/i18n/de.json +15 -0
  4. package/admin/i18n/en.json +15 -0
  5. package/admin/i18n/es.json +18 -0
  6. package/admin/i18n/fr.json +18 -0
  7. package/admin/i18n/it.json +18 -0
  8. package/admin/i18n/nl.json +18 -0
  9. package/admin/i18n/pl.json +18 -0
  10. package/admin/i18n/pt.json +18 -0
  11. package/admin/i18n/ru.json +18 -0
  12. package/admin/i18n/uk.json +18 -0
  13. package/admin/i18n/zh-cn.json +18 -0
  14. package/admin/jsonConfig.json +96 -0
  15. package/io-package.json +60 -49
  16. package/package.json +36 -49
  17. package/src/controls/AalEmergency.ts +90 -0
  18. package/src/controls/AalSmartAlarm.ts +99 -0
  19. package/src/controls/Alarm.ts +146 -0
  20. package/src/controls/AlarmClock.ts +137 -0
  21. package/src/controls/Application.ts +13 -0
  22. package/src/controls/AudioZone.ts +227 -0
  23. package/src/controls/AudioZoneV2.ts +135 -0
  24. package/src/controls/CentralAlarm.ts +59 -0
  25. package/src/controls/CentralAudioZone.ts +41 -0
  26. package/src/controls/CentralGate.ts +53 -0
  27. package/src/controls/CentralJalousie.ts +67 -0
  28. package/src/controls/CentralLightController.ts +45 -0
  29. package/src/controls/ColorPickerV2.ts +34 -0
  30. package/src/controls/Colorpicker.ts +30 -0
  31. package/src/controls/ColorpickerBase.ts +326 -0
  32. package/src/controls/Daytimer.ts +201 -0
  33. package/src/controls/Dimmer.ts +64 -0
  34. package/src/controls/EIBDimmer.ts +61 -0
  35. package/src/controls/Fronius.ts +217 -0
  36. package/src/controls/Gate.ts +150 -0
  37. package/src/controls/Hourcounter.ts +115 -0
  38. package/src/controls/IRCDaytimer.ts +4 -0
  39. package/src/controls/IRCV2Daytimer.ts +4 -0
  40. package/src/controls/IRoomControllerV2.ts +595 -0
  41. package/src/controls/InfoOnlyAnalog.ts +56 -0
  42. package/src/controls/InfoOnlyDigital.ts +95 -0
  43. package/src/controls/InfoOnlyText.ts +52 -0
  44. package/{build/controls/Intercom.js → src/controls/Intercom.ts} +27 -11
  45. package/src/controls/Jalousie.ts +219 -0
  46. package/src/controls/LightController.ts +112 -0
  47. package/src/controls/LightControllerV2.ts +246 -0
  48. package/src/controls/MailBox.ts +92 -0
  49. package/src/controls/Meter.ts +94 -0
  50. package/src/controls/None.ts +29 -0
  51. package/src/controls/PresenceDetector.ts +47 -0
  52. package/src/controls/Pushbutton.ts +55 -0
  53. package/src/controls/Radio.ts +61 -0
  54. package/{build/controls/Remote.js → src/controls/Remote.ts} +19 -11
  55. package/src/controls/Slider.ts +78 -0
  56. package/src/controls/SmokeAlarm.ts +163 -0
  57. package/src/controls/Switch.ts +46 -0
  58. package/src/controls/SystemScheme.ts +13 -0
  59. package/src/controls/TextInput.ts +96 -0
  60. package/src/controls/TextState.ts +37 -0
  61. package/src/controls/TimedSwitch.ts +75 -0
  62. package/src/controls/Tracker.ts +30 -0
  63. package/{build/controls/Unknown.js → src/controls/Unknown.ts} +18 -11
  64. package/src/controls/UpDownAnalog.ts +78 -0
  65. package/{build/controls/ValueSelector.js → src/controls/ValueSelector.ts} +21 -9
  66. package/src/controls/WindowMonitor.ts +139 -0
  67. package/src/controls/all-controls.ts +99 -0
  68. package/src/controls/control-base.ts +28 -0
  69. package/src/lib/adapter-config.d.ts +22 -0
  70. package/src/loxone-handler-base.ts +285 -0
  71. package/src/lxcommunicator.d.ts +1 -0
  72. package/src/main.test.ts +24 -0
  73. package/{build/main.js → src/main.ts} +516 -310
  74. package/src/structure-file.d.ts +154 -0
  75. package/src/weather-server-handler.ts +266 -0
  76. package/admin/admin.d.ts +0 -58
  77. package/admin/index_m.html +0 -126
  78. package/admin/style.css +0 -32
  79. package/admin/words.js +0 -25
  80. package/build/controls/AalEmergency.js +0 -45
  81. package/build/controls/AalEmergency.js.map +0 -1
  82. package/build/controls/AalSmartAlarm.js +0 -48
  83. package/build/controls/AalSmartAlarm.js.map +0 -1
  84. package/build/controls/Alarm.js +0 -81
  85. package/build/controls/Alarm.js.map +0 -1
  86. package/build/controls/AlarmClock.js +0 -59
  87. package/build/controls/AlarmClock.js.map +0 -1
  88. package/build/controls/Application.js +0 -11
  89. package/build/controls/Application.js.map +0 -1
  90. package/build/controls/AudioZone.js +0 -116
  91. package/build/controls/AudioZone.js.map +0 -1
  92. package/build/controls/CentralAlarm.js +0 -30
  93. package/build/controls/CentralAlarm.js.map +0 -1
  94. package/build/controls/CentralAudioZone.js +0 -22
  95. package/build/controls/CentralAudioZone.js.map +0 -1
  96. package/build/controls/CentralGate.js +0 -30
  97. package/build/controls/CentralGate.js.map +0 -1
  98. package/build/controls/CentralJalousie.js +0 -39
  99. package/build/controls/CentralJalousie.js.map +0 -1
  100. package/build/controls/CentralLightController.js +0 -27
  101. package/build/controls/CentralLightController.js.map +0 -1
  102. package/build/controls/ColorPickerV2.js +0 -24
  103. package/build/controls/ColorPickerV2.js.map +0 -1
  104. package/build/controls/Colorpicker.js +0 -20
  105. package/build/controls/Colorpicker.js.map +0 -1
  106. package/build/controls/ColorpickerBase.js +0 -263
  107. package/build/controls/ColorpickerBase.js.map +0 -1
  108. package/build/controls/Daytimer.js +0 -119
  109. package/build/controls/Daytimer.js.map +0 -1
  110. package/build/controls/Dimmer.js +0 -34
  111. package/build/controls/Dimmer.js.map +0 -1
  112. package/build/controls/EIBDimmer.js +0 -31
  113. package/build/controls/EIBDimmer.js.map +0 -1
  114. package/build/controls/Fronius.js +0 -64
  115. package/build/controls/Fronius.js.map +0 -1
  116. package/build/controls/Gate.js +0 -104
  117. package/build/controls/Gate.js.map +0 -1
  118. package/build/controls/Hourcounter.js +0 -46
  119. package/build/controls/Hourcounter.js.map +0 -1
  120. package/build/controls/IRCDaytimer.js +0 -9
  121. package/build/controls/IRCDaytimer.js.map +0 -1
  122. package/build/controls/IRCV2Daytimer.js +0 -9
  123. package/build/controls/IRCV2Daytimer.js.map +0 -1
  124. package/build/controls/IRoomControllerV2.js +0 -371
  125. package/build/controls/IRoomControllerV2.js.map +0 -1
  126. package/build/controls/InfoOnlyAnalog.js +0 -38
  127. package/build/controls/InfoOnlyAnalog.js.map +0 -1
  128. package/build/controls/InfoOnlyDigital.js +0 -65
  129. package/build/controls/InfoOnlyDigital.js.map +0 -1
  130. package/build/controls/InfoOnlyText.js +0 -35
  131. package/build/controls/InfoOnlyText.js.map +0 -1
  132. package/build/controls/Intercom.js.map +0 -1
  133. package/build/controls/Jalousie.js +0 -153
  134. package/build/controls/Jalousie.js.map +0 -1
  135. package/build/controls/LightController.js +0 -68
  136. package/build/controls/LightController.js.map +0 -1
  137. package/build/controls/LightControllerV2.js +0 -195
  138. package/build/controls/LightControllerV2.js.map +0 -1
  139. package/build/controls/MailBox.js +0 -41
  140. package/build/controls/MailBox.js.map +0 -1
  141. package/build/controls/Meter.js +0 -52
  142. package/build/controls/Meter.js.map +0 -1
  143. package/build/controls/None.js +0 -23
  144. package/build/controls/None.js.map +0 -1
  145. package/build/controls/PresenceDetector.js +0 -29
  146. package/build/controls/PresenceDetector.js.map +0 -1
  147. package/build/controls/Pushbutton.js +0 -35
  148. package/build/controls/Pushbutton.js.map +0 -1
  149. package/build/controls/Radio.js +0 -39
  150. package/build/controls/Radio.js.map +0 -1
  151. package/build/controls/Remote.js.map +0 -1
  152. package/build/controls/Slider.js +0 -44
  153. package/build/controls/Slider.js.map +0 -1
  154. package/build/controls/SmokeAlarm.js +0 -85
  155. package/build/controls/SmokeAlarm.js.map +0 -1
  156. package/build/controls/Switch.js +0 -31
  157. package/build/controls/Switch.js.map +0 -1
  158. package/build/controls/SystemScheme.js +0 -11
  159. package/build/controls/SystemScheme.js.map +0 -1
  160. package/build/controls/TextInput.js +0 -55
  161. package/build/controls/TextInput.js.map +0 -1
  162. package/build/controls/TextState.js +0 -20
  163. package/build/controls/TextState.js.map +0 -1
  164. package/build/controls/TimedSwitch.js +0 -36
  165. package/build/controls/TimedSwitch.js.map +0 -1
  166. package/build/controls/Tracker.js +0 -20
  167. package/build/controls/Tracker.js.map +0 -1
  168. package/build/controls/Unknown.js.map +0 -1
  169. package/build/controls/UpDownAnalog.js +0 -44
  170. package/build/controls/UpDownAnalog.js.map +0 -1
  171. package/build/controls/ValueSelector.js.map +0 -1
  172. package/build/controls/WindowMonitor.js +0 -84
  173. package/build/controls/WindowMonitor.js.map +0 -1
  174. package/build/controls/control-base.js +0 -12
  175. package/build/controls/control-base.js.map +0 -1
  176. package/build/loxone-handler-base.js +0 -186
  177. package/build/loxone-handler-base.js.map +0 -1
  178. package/build/main.js.map +0 -1
  179. package/build/weather-server-handler.js +0 -120
  180. package/build/weather-server-handler.js.map +0 -1
  181. package/doc/details-missing-control-type.png +0 -0
  182. package/doc/log-missing-control-type.png +0 -0
  183. package/doc/loxone-config-display-diagnostics.png +0 -0
  184. package/doc/loxone-config-info-only-digital.png +0 -0
  185. package/doc/loxone-config-use-in-visualization.png +0 -0
@@ -0,0 +1,246 @@
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 LightControllerV2 controls.
8
+ */
9
+ export class LightControllerV2 extends ControlBase {
10
+ private activeMoods: string[] = [];
11
+ private favoriteMoods: string[] = [];
12
+ private additionalMoods: string[] = [];
13
+
14
+ private idToMoodName: Record<string, string> = {};
15
+ private moodNameToId: Record<string, string> = {};
16
+
17
+ private uuid = '';
18
+
19
+ /**
20
+ * Loads the control and sets up state objects and event handlers.
21
+ *
22
+ * @param type The type of the control ('device' or 'channel').
23
+ * @param uuid The unique identifier of the control.
24
+ * @param control The control data from the structure file.
25
+ */
26
+ async loadAsync(type: ControlType, uuid: string, control: Control): Promise<void> {
27
+ this.uuid = uuid;
28
+ await this.updateObjectAsync(uuid, {
29
+ type: type,
30
+ common: {
31
+ name: control.name,
32
+ role: 'light',
33
+ },
34
+ native: { control },
35
+ });
36
+
37
+ await this.loadOtherControlStatesAsync(control.name, uuid, control.states, [
38
+ 'activeMoods',
39
+ 'moodList',
40
+ 'favoriteMoods',
41
+ 'additionalMoods',
42
+ ]);
43
+
44
+ if (
45
+ 'activeMoods' in control.states &&
46
+ 'moodList' in control.states &&
47
+ 'favoriteMoods' in control.states &&
48
+ 'additionalMoods' in control.states
49
+ ) {
50
+ await this.updateStateObjectAsync(
51
+ `${uuid}.moodList`,
52
+ {
53
+ name: `${control.name}: moodList`,
54
+ read: true,
55
+ write: false,
56
+ type: 'array',
57
+ role: 'list',
58
+ // TODO: re-add: smartIgnore: true,
59
+ },
60
+ control.states.moodList,
61
+ async (name: string, value: any) => {
62
+ const moodList = JSON.parse(value);
63
+ const list = [];
64
+ this.idToMoodName = {};
65
+ this.moodNameToId = {};
66
+ for (const index in moodList) {
67
+ const mood = moodList[index];
68
+ if ('id' in mood && 'name' in mood) {
69
+ this.idToMoodName[mood.id] = mood.name;
70
+ this.moodNameToId[mood.name] = mood.id;
71
+ list.push(mood.name);
72
+ }
73
+ }
74
+ await this.updateActiveMoods();
75
+ await this.updateFavoriteMoods();
76
+ await this.updateAdditionalMoods();
77
+
78
+ await this.setStateAck(name, JSON.stringify(list));
79
+ },
80
+ );
81
+ await this.updateStateObjectAsync(
82
+ `${uuid}.activeMoods`,
83
+ {
84
+ name: `${control.name}: activeMoods`,
85
+ read: true,
86
+ write: true,
87
+ type: 'array',
88
+ role: 'list',
89
+ // TODO: re-add: smartIgnore: true,
90
+ },
91
+ control.states.activeMoods,
92
+ async (name: string, value: any) => {
93
+ this.activeMoods = JSON.parse(value);
94
+ await this.updateActiveMoods();
95
+ },
96
+ );
97
+ this.addStateChangeListener(
98
+ `${uuid}.activeMoods`,
99
+ (oldValue: OldStateValue, newValue: CurrentStateValue) => {
100
+ let arrayValue: string[];
101
+ if (Array.isArray(newValue)) {
102
+ arrayValue = newValue;
103
+ } else {
104
+ try {
105
+ newValue = JSON.parse(newValue as string);
106
+ } catch {
107
+ // ignore error, continue below
108
+ }
109
+ if (!Array.isArray(newValue)) {
110
+ arrayValue = (newValue as string).split(',');
111
+ } else {
112
+ arrayValue = newValue;
113
+ }
114
+ }
115
+
116
+ const ids = [];
117
+ for (let i = 0; i < arrayValue.length; i++) {
118
+ const moodName = arrayValue[i];
119
+ if (!(moodName in this.moodNameToId)) {
120
+ this.adapter.log.warn(`Can't find mood name '${moodName}', discarding new value`);
121
+ return;
122
+ }
123
+ ids.push(this.moodNameToId[moodName]);
124
+ }
125
+ if (ids.length === 0) {
126
+ this.adapter.log.warn(`${uuid}.activeMoods can't have zero IDs, discarding new value`);
127
+ return;
128
+ }
129
+
130
+ const addMoods = [];
131
+ const removeMoods = [];
132
+ let hasKeepMoods = false;
133
+ for (let i = 0; i < ids.length; i++) {
134
+ if (this.activeMoods.includes(ids[i])) {
135
+ hasKeepMoods = true;
136
+ } else {
137
+ addMoods.push(ids[i]);
138
+ }
139
+ }
140
+ for (let i = 0; i < this.activeMoods.length; i++) {
141
+ if (!ids.includes(this.activeMoods[i])) {
142
+ removeMoods.push(this.activeMoods[i]);
143
+ }
144
+ }
145
+ if (hasKeepMoods) {
146
+ for (let i = 0; i < removeMoods.length; i++) {
147
+ this.sendCommand(control.uuidAction, `removeMood/${removeMoods[i]}`);
148
+ }
149
+ } else {
150
+ const firstId = addMoods.shift();
151
+ this.sendCommand(control.uuidAction, `changeTo/${firstId}`);
152
+ }
153
+
154
+ for (let i = 0; i < addMoods.length; i++) {
155
+ this.sendCommand(control.uuidAction, `addMood/${addMoods[i]}`);
156
+ }
157
+ },
158
+ );
159
+ await this.updateStateObjectAsync(
160
+ `${uuid}.favoriteMoods`,
161
+ {
162
+ name: `${control.name}: favoriteMoods`,
163
+ read: true,
164
+ write: false,
165
+ type: 'array',
166
+ role: 'list',
167
+ // TODO: re-add: smartIgnore: true,
168
+ },
169
+ control.states.favoriteMoods,
170
+ async (id: string, value: any) => {
171
+ this.favoriteMoods = JSON.parse(value);
172
+ await this.updateFavoriteMoods();
173
+ },
174
+ );
175
+ await this.updateStateObjectAsync(
176
+ `${uuid}.additionalMoods`,
177
+ {
178
+ name: `${control.name}: additionalMoods`,
179
+ read: true,
180
+ write: false,
181
+ type: 'array',
182
+ role: 'list',
183
+ // TODO: re-add: smartIgnore: true,
184
+ },
185
+ control.states.additionalMoods,
186
+ async (name: string, value: any) => {
187
+ this.additionalMoods = JSON.parse(value);
188
+ await this.updateAdditionalMoods();
189
+ },
190
+ );
191
+ }
192
+
193
+ await this.createButtonCommandStateObjectAsync(control.name, uuid, 'plus');
194
+ this.addStateChangeListener(
195
+ `${uuid}.plus`,
196
+ () => {
197
+ this.sendCommand(control.uuidAction, 'plus');
198
+ },
199
+ { selfAck: true },
200
+ );
201
+
202
+ await this.createButtonCommandStateObjectAsync(control.name, uuid, 'minus');
203
+ this.addStateChangeListener(
204
+ `${uuid}.minus`,
205
+ () => {
206
+ this.sendCommand(control.uuidAction, 'minus');
207
+ },
208
+ { selfAck: true },
209
+ );
210
+
211
+ // TODO: add Alexa support! (how???)
212
+
213
+ // TODO: currently we don't support scene modifications ("learn" and "delete" commands),
214
+ // IMHO this should be done by the user through the Loxone Web interface
215
+
216
+ await this.loadSubControlsAsync(uuid, control);
217
+ }
218
+
219
+ private async updateMoodsList(name: string, idList: string[]): Promise<void> {
220
+ if (Object.keys(this.idToMoodName).length === 0) {
221
+ return;
222
+ }
223
+ const list = [];
224
+ for (const id of idList) {
225
+ if (id in this.idToMoodName) {
226
+ list.push(this.idToMoodName[id]);
227
+ } else {
228
+ list.push(id);
229
+ }
230
+ }
231
+
232
+ await this.setStateAck(`${this.uuid}.${name}`, JSON.stringify(list));
233
+ }
234
+
235
+ private async updateActiveMoods(): Promise<void> {
236
+ await this.updateMoodsList('activeMoods', this.activeMoods);
237
+ }
238
+
239
+ private async updateFavoriteMoods(): Promise<void> {
240
+ await this.updateMoodsList('favoriteMoods', this.favoriteMoods);
241
+ }
242
+
243
+ private async updateAdditionalMoods(): Promise<void> {
244
+ await this.updateMoodsList('additionalMoods', this.additionalMoods);
245
+ }
246
+ }
@@ -0,0 +1,92 @@
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 MailBox controls.
8
+ */
9
+ export class MailBox 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: 'info',
23
+ },
24
+ native: { control },
25
+ });
26
+
27
+ await this.loadOtherControlStatesAsync(control.name, uuid, control.states, [
28
+ 'notificationsDisabledInput',
29
+ 'packetReceived',
30
+ 'mailReceived',
31
+ 'disableEndTime',
32
+ ]);
33
+
34
+ await this.createBooleanControlStateObjectAsync(
35
+ control.name,
36
+ uuid,
37
+ control.states,
38
+ 'notificationsDisabledInput',
39
+ 'indicator',
40
+ );
41
+ await this.createBooleanControlStateObjectAsync(
42
+ control.name,
43
+ uuid,
44
+ control.states,
45
+ 'packetReceived',
46
+ 'indicator',
47
+ );
48
+ await this.createBooleanControlStateObjectAsync(
49
+ control.name,
50
+ uuid,
51
+ control.states,
52
+ 'mailReceived',
53
+ 'indicator',
54
+ );
55
+ await this.createSimpleControlStateObjectAsync(
56
+ control.name,
57
+ uuid,
58
+ control.states,
59
+ 'disableEndTime',
60
+ 'number',
61
+ 'value.interval',
62
+ );
63
+
64
+ await this.createButtonCommandStateObjectAsync(control.name, uuid, 'confirmPacket');
65
+ this.addStateChangeListener(
66
+ `${uuid}.confirmPacket`,
67
+ () => {
68
+ this.sendCommand(control.uuidAction, 'confirmPacket');
69
+ },
70
+ { selfAck: true },
71
+ );
72
+
73
+ await this.createButtonCommandStateObjectAsync(control.name, uuid, 'confirmMail');
74
+ this.addStateChangeListener(
75
+ `${uuid}.confirmMail`,
76
+ () => {
77
+ this.sendCommand(control.uuidAction, 'confirmMail');
78
+ },
79
+ { selfAck: true },
80
+ );
81
+
82
+ await this.createNumberInputStateObjectAsync(control.name, uuid, 'disableNotifications', 'level.timer');
83
+ this.addStateChangeListener(
84
+ `${uuid}.disableNotifications`,
85
+ (oldValue: OldStateValue, newValue: CurrentStateValue) => {
86
+ this.sendCommand(control.uuidAction, `disableNotifications/${newValue || '0'}`);
87
+ },
88
+ );
89
+
90
+ await this.loadSubControlsAsync(uuid, control);
91
+ }
92
+ }
@@ -0,0 +1,94 @@
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 Meter controls.
7
+ */
8
+ export class Meter 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, ['actual', 'total']);
27
+
28
+ await this.createSimpleControlStateObjectAsync(
29
+ control.name,
30
+ uuid,
31
+ control.states,
32
+ 'actual',
33
+ 'number',
34
+ 'value.power.consumption',
35
+ );
36
+ await this.createSimpleControlStateObjectAsync(
37
+ control.name,
38
+ uuid,
39
+ control.states,
40
+ 'total',
41
+ 'number',
42
+ 'value.power.consumption',
43
+ );
44
+
45
+ await this.createButtonCommandStateObjectAsync(control.name, uuid, 'reset');
46
+ this.addStateChangeListener(
47
+ `${uuid}.reset`,
48
+ () => {
49
+ this.sendCommand(control.uuidAction, 'reset');
50
+ },
51
+ { selfAck: true },
52
+ );
53
+
54
+ if (!('details' in control)) {
55
+ return;
56
+ }
57
+
58
+ if ('actualFormat' in control.details) {
59
+ await this.updateStateObjectAsync(
60
+ `${uuid}.actual-formatted`,
61
+ {
62
+ name: `${control.name}: formatted actual value`,
63
+ read: true,
64
+ write: false,
65
+ type: 'string',
66
+ role: 'text',
67
+ // TODO: re-add: smartIgnore: true,
68
+ },
69
+ control.states.actual,
70
+ async (name: string, value: any) => {
71
+ await this.setFormattedStateAck(name, value, control.details.actualFormat as string);
72
+ },
73
+ );
74
+ }
75
+
76
+ if ('totalFormat' in control.details) {
77
+ await this.updateStateObjectAsync(
78
+ `${uuid}.total-formatted`,
79
+ {
80
+ name: `${control.name}: formatted total value`,
81
+ read: true,
82
+ write: false,
83
+ type: 'string',
84
+ role: 'text',
85
+ // TODO: re-add: smartIgnore: true,
86
+ },
87
+ control.states.total,
88
+ async (name: string, value: any) => {
89
+ await this.setFormattedStateAck(name, value, control.details.totalFormat as string);
90
+ },
91
+ );
92
+ }
93
+ }
94
+ }
@@ -0,0 +1,29 @@
1
+ import type { Control } from '../structure-file';
2
+ import type { ControlType } from './control-base';
3
+ import { ControlBase } from './control-base';
4
+
5
+ /**
6
+ * This class is used if the control has no type (currently seems to be only for window monitoring).
7
+ * It will just load the simple default states.
8
+ */
9
+ export class None 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: 'info',
23
+ },
24
+ native: { control },
25
+ });
26
+
27
+ await this.loadOtherControlStatesAsync(control.name, uuid, control.states, []);
28
+ }
29
+ }
@@ -0,0 +1,47 @@
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 PresenceDetector controls.
7
+ */
8
+ export class PresenceDetector 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, [
27
+ 'active',
28
+ 'locked',
29
+ 'events',
30
+ 'infoText',
31
+ ]);
32
+
33
+ await this.createBooleanControlStateObjectAsync(control.name, uuid, control.states, 'active', 'indicator');
34
+ await this.createBooleanControlStateObjectAsync(control.name, uuid, control.states, 'locked', 'indicator');
35
+ await this.createSimpleControlStateObjectAsync(control.name, uuid, control.states, 'events', 'number', 'value');
36
+ await this.createSimpleControlStateObjectAsync(
37
+ control.name,
38
+ uuid,
39
+ control.states,
40
+ 'infoText',
41
+ 'string',
42
+ 'text',
43
+ );
44
+
45
+ await this.loadSubControlsAsync(uuid, control);
46
+ }
47
+ }
@@ -0,0 +1,55 @@
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 Pushbutton controls.
8
+ */
9
+ export class Pushbutton 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: 'switch',
23
+ },
24
+ native: { control },
25
+ });
26
+
27
+ await this.loadOtherControlStatesAsync(control.name, uuid, control.states, ['active']);
28
+
29
+ await this.createBooleanControlStateObjectAsync(control.name, uuid, control.states, 'active', 'switch', {
30
+ write: true,
31
+ // TODO: re-add: smartIgnore: type == 'channel',
32
+ });
33
+
34
+ this.addStateChangeListener(
35
+ `${uuid}.active`,
36
+ (oldValue: OldStateValue, newValue: CurrentStateValue) => {
37
+ if (newValue) {
38
+ this.sendCommand(control.uuidAction, 'on');
39
+ } else {
40
+ this.sendCommand(control.uuidAction, 'off');
41
+ }
42
+ },
43
+ { notIfEqual: true },
44
+ );
45
+
46
+ await this.createButtonCommandStateObjectAsync(control.name, uuid, 'pulse');
47
+ this.addStateChangeListener(
48
+ `${uuid}.pulse`,
49
+ () => {
50
+ this.sendCommand(control.uuidAction, 'pulse');
51
+ },
52
+ { selfAck: true },
53
+ );
54
+ }
55
+ }
@@ -0,0 +1,61 @@
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 Radio controls.
8
+ */
9
+ export class Radio 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: 'button',
23
+ },
24
+ native: { control },
25
+ });
26
+
27
+ await this.loadOtherControlStatesAsync(control.name, uuid, control.states, ['activeOutput']);
28
+
29
+ let states: Record<string, string> = {};
30
+ if ('allOff' in control.details) {
31
+ states['0'] = control.details.allOff as string;
32
+ }
33
+ if ('outputs' in control.details) {
34
+ states = { ...states, ...(control.details.outputs as Record<string, string>) };
35
+ }
36
+ await this.createSimpleControlStateObjectAsync(
37
+ control.name,
38
+ uuid,
39
+ control.states,
40
+ 'activeOutput',
41
+ 'number',
42
+ 'level',
43
+ {
44
+ states,
45
+ write: true,
46
+ },
47
+ );
48
+ this.addStateChangeListener(
49
+ `${uuid}.activeOutput`,
50
+ (oldValue: OldStateValue, newValue: CurrentStateValue) => {
51
+ const value = this.convertStateToInt(newValue);
52
+ if (value === 0) {
53
+ this.sendCommand(control.uuidAction, 'reset');
54
+ } else if (value in states) {
55
+ this.sendCommand(control.uuidAction, value.toString());
56
+ }
57
+ },
58
+ { notIfEqual: true },
59
+ );
60
+ }
61
+ }
@@ -1,13 +1,22 @@
1
1
  'use strict';
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Remote = void 0;
4
- const control_base_1 = require("./control-base");
2
+ import type { CurrentStateValue, OldStateValue } from '../main';
3
+ import type { Control } from '../structure-file';
4
+ import type { ControlType } from './control-base';
5
+ import { ControlBase } from './control-base';
6
+
5
7
  /**
6
8
  * Remote aka. Media Controller
7
9
  */
8
- class Remote extends control_base_1.ControlBase {
9
- async loadAsync(type, uuid, control) {
10
- this.adapter.log.debug('Remote controls: ' + JSON.stringify(control));
10
+ export class Remote extends ControlBase {
11
+ /**
12
+ * Loads the control and sets up state objects and event handlers.
13
+ *
14
+ * @param type The type of the control ('device' or 'channel').
15
+ * @param uuid The unique identifier of the control.
16
+ * @param control The control data from the structure file.
17
+ */
18
+ async loadAsync(type: ControlType, uuid: string, control: Control): Promise<void> {
19
+ this.adapter.log.debug(`Remote controls: ${JSON.stringify(control)}`);
11
20
  await this.updateObjectAsync(uuid, {
12
21
  type: type,
13
22
  common: {
@@ -16,21 +25,20 @@ class Remote extends control_base_1.ControlBase {
16
25
  },
17
26
  native: { control },
18
27
  });
28
+
19
29
  await this.loadOtherControlStatesAsync(control.name, uuid, control.states, ['jLocked', 'mode']);
30
+
20
31
  await this.createSimpleControlStateObjectAsync(control.name, uuid, control.states, 'mode', 'string', 'text', {
21
32
  write: true,
22
33
  });
23
- this.addStateChangeListener(uuid + '.mode', (oldValue, newValue) => {
34
+ this.addStateChangeListener(`${uuid}.mode`, (oldValue: OldStateValue, newValue: CurrentStateValue) => {
24
35
  if (newValue && newValue !== '0') {
25
36
  // Send the actual mode number
26
37
  this.sendCommand(control.uuidAction, `mode/${newValue}`);
27
- }
28
- else {
38
+ } else {
29
39
  // Sending mode zero is not supported so sent reset/all off
30
40
  this.sendCommand(control.uuidAction, 'reset');
31
41
  }
32
42
  });
33
43
  }
34
44
  }
35
- exports.Remote = Remote;
36
- //# sourceMappingURL=Remote.js.map