hoffmation-base 3.4.9 → 3.6.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/lib/api/api-service.d.ts +9 -12
- package/lib/api/api-service.js +13 -28
- package/lib/command/acPerformAutomaticCheckCommand.d.ts +18 -0
- package/lib/command/acPerformAutomaticCheckCommand.js +25 -0
- package/lib/command/acSetStateCommand.d.ts +34 -0
- package/lib/command/acSetStateCommand.js +40 -0
- package/lib/command/acWriteStateToDeviceCommand.d.ts +25 -0
- package/lib/command/acWriteStateToDeviceCommand.js +30 -0
- package/lib/command/excessEnergyConsumerSetStateCommand.d.ts +19 -0
- package/lib/command/excessEnergyConsumerSetStateCommand.js +26 -0
- package/lib/command/index.d.ts +4 -0
- package/lib/command/index.js +9 -1
- package/lib/devices/groups/heatGroup.d.ts +6 -3
- package/lib/devices/groups/heatGroup.js +19 -8
- package/lib/devices/groups/tasterGroup.js +5 -2
- package/lib/devices/jsObject/jsObjectEnergyManager.js +3 -4
- package/lib/devices/sharedFunctions/shutterUtils.js +7 -2
- package/lib/devices/tv/tvDevice.d.ts +2 -1
- package/lib/devices/tv/tvDevice.js +5 -1
- package/lib/devices/victron/victron-device.js +3 -4
- package/lib/devices/zigbee/zigbeeBlitzShp.d.ts +2 -3
- package/lib/devices/zigbee/zigbeeBlitzShp.js +5 -7
- package/lib/enums/commandType.d.ts +4 -0
- package/lib/enums/commandType.js +4 -0
- package/lib/interfaces/baseDevices/iAcDevice.d.ts +14 -4
- package/lib/interfaces/baseDevices/iExcessEnergyConsumer.d.ts +7 -6
- package/lib/interfaces/groups/iHeatGroup.d.ts +4 -3
- package/lib/services/ac/ac-device.d.ts +45 -13
- package/lib/services/ac/ac-device.js +97 -33
- package/lib/services/ac/daikin-service.d.ts +2 -1
- package/lib/services/ac/daikin-service.js +8 -13
- package/lib/services/ac/own-daikin-device.d.ts +4 -3
- package/lib/services/ac/own-daikin-device.js +6 -6
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { iAcSettings } from '../deviceSettings';
|
|
2
2
|
import { iBaseDevice } from './iBaseDevice';
|
|
3
3
|
import { AcMode } from '../../enums';
|
|
4
|
+
import { AcSetStateCommand, AcWriteStateToDeviceCommand } from '../../command';
|
|
4
5
|
/**
|
|
5
6
|
* Interface for normal air-conditioning devices
|
|
6
7
|
*
|
|
7
8
|
* For devices with {@link DeviceCapability.ac} capability.
|
|
8
|
-
* TODO: Migrate to new Command-Based System
|
|
9
9
|
* TODO: Extend from iActuator
|
|
10
10
|
*/
|
|
11
11
|
export interface iAcDevice extends iBaseDevice {
|
|
@@ -48,21 +48,31 @@ export interface iAcDevice extends iBaseDevice {
|
|
|
48
48
|
* @param writeToDevice - Whether to write the new mode to the device
|
|
49
49
|
*/
|
|
50
50
|
setDesiredMode(mode: AcMode, writeToDevice: boolean): void;
|
|
51
|
+
/**
|
|
52
|
+
* Performs a power write, applying any automatic block the command carries
|
|
53
|
+
* @param c - The command to execute
|
|
54
|
+
*/
|
|
55
|
+
writeStateToDevice(c: AcWriteStateToDeviceCommand): void;
|
|
51
56
|
/**
|
|
52
57
|
* Turns the air-conditioning device on without changing the settings
|
|
58
|
+
* @param c - The command to execute
|
|
53
59
|
*/
|
|
54
|
-
turnOn(): void;
|
|
60
|
+
turnOn(c: AcWriteStateToDeviceCommand): void;
|
|
55
61
|
/**
|
|
56
62
|
* Turns the air-conditioning device off
|
|
63
|
+
* @param c - The command to execute
|
|
57
64
|
*/
|
|
58
|
-
turnOff(): void;
|
|
65
|
+
turnOff(c: AcWriteStateToDeviceCommand): void;
|
|
59
66
|
/**
|
|
60
67
|
* Calculates the desired mode based on the current settings and the room temperature
|
|
61
68
|
* @returns The desired mode
|
|
62
69
|
*/
|
|
63
70
|
calculateDesiredMode(): AcMode;
|
|
64
71
|
/**
|
|
72
|
+
* Sets the state of the air-conditioning device.
|
|
65
73
|
*
|
|
74
|
+
* Single entry point for every state change, so each one is recorded in the command log.
|
|
75
|
+
* @param c - The command to execute
|
|
66
76
|
*/
|
|
67
|
-
|
|
77
|
+
setAcState(c: AcSetStateCommand): void;
|
|
68
78
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { iBaseDevice } from './iBaseDevice';
|
|
2
2
|
import { iExcessEnergyConsumerSettings } from '../settings';
|
|
3
|
+
import { ExcessEnergyConsumerSetStateCommand } from '../../command';
|
|
3
4
|
/**
|
|
4
5
|
* This interface represents a device that can consume excess energy.
|
|
5
6
|
*
|
|
@@ -25,13 +26,13 @@ export interface iExcessEnergyConsumer extends iBaseDevice {
|
|
|
25
26
|
*/
|
|
26
27
|
isAvailableForExcessEnergy(): boolean;
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
+
* Start or stop this device following an energy-manager decision.
|
|
30
|
+
*
|
|
31
|
+
* One entry point rather than separate turn-on/turn-off methods, so the desired state can
|
|
32
|
+
* only come from the command and cannot contradict the method that was called.
|
|
33
|
+
* @param c - The decision this results from, carrying the measurement it was based on
|
|
29
34
|
*/
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Turn off this device as we don't have enough excess energy to power it
|
|
33
|
-
*/
|
|
34
|
-
turnOffDueToMissingEnergy(): void;
|
|
35
|
+
setExcessEnergyState(c: ExcessEnergyConsumerSetStateCommand): void;
|
|
35
36
|
/**
|
|
36
37
|
* Check if this device was activated by excess energy
|
|
37
38
|
* @returns Whether this device was activated by excess energy
|
|
@@ -2,6 +2,8 @@ import { iBaseGroup } from './iBaseGroup';
|
|
|
2
2
|
import { iAcDevice, iHeater, iHumidityCollector, iTemperatureCollector } from '../baseDevices';
|
|
3
3
|
import { iTemperatureSettings } from '../settings';
|
|
4
4
|
import { iHeatGroupSettings } from './iHeatGroupSettings';
|
|
5
|
+
import { CommandSource } from '../../enums';
|
|
6
|
+
import { iBaseCommand } from '../../command';
|
|
5
7
|
/**
|
|
6
8
|
*
|
|
7
9
|
*/
|
|
@@ -44,11 +46,10 @@ export interface iHeatGroup extends iBaseGroup {
|
|
|
44
46
|
initialize(): void;
|
|
45
47
|
/**
|
|
46
48
|
* Sets all ACs to new desired Value
|
|
47
|
-
* TODO: Migrate to new Command System
|
|
48
49
|
* @param newDesiredState - The new desired (on/off) state
|
|
49
|
-
* @param
|
|
50
|
+
* @param source - The event this results from, so the device command can be traced back to it
|
|
50
51
|
*/
|
|
51
|
-
setAc(newDesiredState: boolean,
|
|
52
|
+
setAc(newDesiredState: boolean, source: CommandSource | iBaseCommand): void;
|
|
52
53
|
/**
|
|
53
54
|
*
|
|
54
55
|
*/
|
|
@@ -2,6 +2,7 @@ import { AcSettings, RoomBaseDevice } from '../../devices';
|
|
|
2
2
|
import { iAcDevice, iExcessEnergyConsumer, iTemporaryDisableAutomatic } from '../../interfaces';
|
|
3
3
|
import { AcDeviceType, AcMode, DeviceType } from '../../enums';
|
|
4
4
|
import { BlockAutomaticHandler } from '../blockAutomaticHandler';
|
|
5
|
+
import { AcPerformAutomaticCheckCommand, AcSetStateCommand, AcWriteStateToDeviceCommand, ExcessEnergyConsumerSetStateCommand, RestoreTargetAutomaticValueCommand } from '../../command';
|
|
5
6
|
import { ExcessEnergyConsumerSettings } from '../../settingsObjects';
|
|
6
7
|
export declare abstract class AcDevice extends RoomBaseDevice implements iExcessEnergyConsumer, iAcDevice, iTemporaryDisableAutomatic {
|
|
7
8
|
ip: string;
|
|
@@ -49,13 +50,22 @@ export declare abstract class AcDevice extends RoomBaseDevice implements iExcess
|
|
|
49
50
|
abstract get on(): boolean;
|
|
50
51
|
initializeRoomCbs(): void;
|
|
51
52
|
/** @inheritDoc */
|
|
52
|
-
restoreTargetAutomaticValue(): void;
|
|
53
|
+
restoreTargetAutomaticValue(c: RestoreTargetAutomaticValueCommand): void;
|
|
53
54
|
/** @inheritDoc */
|
|
54
55
|
isAvailableForExcessEnergy(): boolean;
|
|
55
56
|
/** @inheritDoc */
|
|
56
57
|
calculateDesiredMode(): AcMode;
|
|
57
58
|
abstract setDesiredMode(mode: AcMode, writeToDevice: boolean, temp?: number): void;
|
|
58
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Performs a power write, applying any automatic block the command carries.
|
|
61
|
+
*
|
|
62
|
+
* Single place where a block from a write command is honoured, so callers never have to
|
|
63
|
+
* follow up with a separate disableAutomatic call. A block is not a device setting, so it
|
|
64
|
+
* belongs on a pure power write just as much as on a state change.
|
|
65
|
+
* @param c - The command to execute
|
|
66
|
+
*/
|
|
67
|
+
writeStateToDevice(c: AcWriteStateToDeviceCommand): void;
|
|
68
|
+
abstract turnOn(c: AcWriteStateToDeviceCommand): void;
|
|
59
69
|
/** @inheritDoc */
|
|
60
70
|
onTemperaturChange(newTemperatur: number): void;
|
|
61
71
|
/**
|
|
@@ -63,22 +73,44 @@ export declare abstract class AcDevice extends RoomBaseDevice implements iExcess
|
|
|
63
73
|
*/
|
|
64
74
|
persist(): void;
|
|
65
75
|
/** @inheritDoc */
|
|
66
|
-
|
|
67
|
-
abstract turnOff(): void;
|
|
68
|
-
/** @inheritDoc */
|
|
69
|
-
turnOffDueToMissingEnergy(): void;
|
|
76
|
+
setExcessEnergyState(c: ExcessEnergyConsumerSetStateCommand): void;
|
|
77
|
+
abstract turnOff(c: AcWriteStateToDeviceCommand): void;
|
|
70
78
|
/**
|
|
71
|
-
* Sets the state of the AC
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
79
|
+
* Sets the state of the AC.
|
|
80
|
+
*
|
|
81
|
+
* Single entry point for every state change, so each one lands in the command log and
|
|
82
|
+
* the reason a unit switched can be reconstructed afterwards. Callers that represent an
|
|
83
|
+
* automatic decision pass no disableAutomaticCommand, so they do not block themselves.
|
|
84
|
+
* @param c - The command to execute
|
|
76
85
|
*/
|
|
77
|
-
|
|
86
|
+
setAcState(c: AcSetStateCommand): void;
|
|
78
87
|
/** @inheritDoc */
|
|
79
88
|
wasActivatedByExcessEnergy(): boolean;
|
|
80
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Re-evaluates what the state should be and applies it.
|
|
91
|
+
* @param c - The command asking for the re-evaluation; the resulting device command chains
|
|
92
|
+
* from it, so the log shows what triggered the change
|
|
93
|
+
*/
|
|
94
|
+
protected automaticCheck(c: AcPerformAutomaticCheckCommand): void;
|
|
81
95
|
private onRoomAnyMovement;
|
|
96
|
+
/**
|
|
97
|
+
* Keeps the unit off for as long as the room counts as occupied - renewed by every movement.
|
|
98
|
+
*
|
|
99
|
+
* Without a block, staying off depended on the five-minute interval check noticing that somebody
|
|
100
|
+
* is present, and coming back on depended on the last-leave callback arriving. The block replaces
|
|
101
|
+
* both with one timer: every movement pushes it out, and its expiry reverts to automatic by
|
|
102
|
+
* itself, so the room cools again shortly after it empties rather than at the next check.
|
|
103
|
+
*
|
|
104
|
+
* The duration is the room's own movementResetTimer - the same span that decides when the room
|
|
105
|
+
* counts as empty. Anything shorter would let the unit start up with somebody still sitting there;
|
|
106
|
+
* a separate constant would be a second answer to a question the room already answers.
|
|
107
|
+
*
|
|
108
|
+
* The collision strategy is deliberately left at its default (overrideIfGreater): a long press on
|
|
109
|
+
* the wall button sets a much longer block, and walking past the unit must not cut that short.
|
|
110
|
+
* @param c - The command the block chains from, so the log shows what triggered it
|
|
111
|
+
* @returns The block, or undefined when the device has no room to take the duration from
|
|
112
|
+
*/
|
|
113
|
+
private buildMovementBlock;
|
|
82
114
|
private onRoomLastLeave;
|
|
83
115
|
/** @inheritDoc */
|
|
84
116
|
toJSON(): Partial<AcDevice>;
|
|
@@ -67,7 +67,7 @@ class AcDevice extends devices_1.RoomBaseDevice {
|
|
|
67
67
|
this.deviceCapabilities.push(enums_1.DeviceCapability.ac);
|
|
68
68
|
this.deviceCapabilities.push(enums_1.DeviceCapability.blockAutomatic);
|
|
69
69
|
this.deviceCapabilities.push(enums_1.DeviceCapability.excessEnergyConsumer);
|
|
70
|
-
utils_1.Utils.guardedInterval(this.automaticCheck, 5 * 60 * 1000, this, false);
|
|
70
|
+
utils_1.Utils.guardedInterval(() => this.automaticCheck(new command_1.AcPerformAutomaticCheckCommand(enums_1.CommandSource.Automatic, 'Time interval check')), 5 * 60 * 1000, this, false);
|
|
71
71
|
utils_1.Utils.guardedInterval(this.persist, 15 * 60 * 1000, this, true);
|
|
72
72
|
this.blockAutomationHandler = new blockAutomaticHandler_1.BlockAutomaticHandler(this.restoreTargetAutomaticValue.bind(this), this.log.bind(this));
|
|
73
73
|
}
|
|
@@ -100,16 +100,14 @@ class AcDevice extends devices_1.RoomBaseDevice {
|
|
|
100
100
|
}
|
|
101
101
|
utils_1.Utils.guardedFunction(() => {
|
|
102
102
|
var _a, _b;
|
|
103
|
-
// TODO: Maybe change to any Movement
|
|
104
103
|
(_a = this.room.PraesenzGroup) === null || _a === void 0 ? void 0 : _a.addAnyMovementCallback(this.onRoomAnyMovement.bind(this));
|
|
105
104
|
(_b = this.room.PraesenzGroup) === null || _b === void 0 ? void 0 : _b.addLastLeftCallback(this.onRoomLastLeave.bind(this));
|
|
106
105
|
this._movementCallbackAdded = true;
|
|
107
106
|
}, this);
|
|
108
107
|
}
|
|
109
108
|
/** @inheritDoc */
|
|
110
|
-
restoreTargetAutomaticValue() {
|
|
111
|
-
this.
|
|
112
|
-
this.automaticCheck();
|
|
109
|
+
restoreTargetAutomaticValue(c) {
|
|
110
|
+
this.automaticCheck(new command_1.AcPerformAutomaticCheckCommand(c, 'Restore automatic value'));
|
|
113
111
|
}
|
|
114
112
|
/** @inheritDoc */
|
|
115
113
|
isAvailableForExcessEnergy() {
|
|
@@ -222,6 +220,24 @@ class AcDevice extends devices_1.RoomBaseDevice {
|
|
|
222
220
|
}
|
|
223
221
|
return desiredMode;
|
|
224
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Performs a power write, applying any automatic block the command carries.
|
|
225
|
+
*
|
|
226
|
+
* Single place where a block from a write command is honoured, so callers never have to
|
|
227
|
+
* follow up with a separate disableAutomatic call. A block is not a device setting, so it
|
|
228
|
+
* belongs on a pure power write just as much as on a state change.
|
|
229
|
+
* @param c - The command to execute
|
|
230
|
+
*/
|
|
231
|
+
writeStateToDevice(c) {
|
|
232
|
+
if (c.disableAutomaticCommand) {
|
|
233
|
+
this.blockAutomationHandler.disableAutomatic(c.disableAutomaticCommand);
|
|
234
|
+
}
|
|
235
|
+
if (c.on) {
|
|
236
|
+
this.turnOn(c);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
this.turnOff(c);
|
|
240
|
+
}
|
|
225
241
|
/** @inheritDoc */
|
|
226
242
|
onTemperaturChange(newTemperatur) {
|
|
227
243
|
this.roomTemperatur = newTemperatur;
|
|
@@ -237,47 +253,67 @@ class AcDevice extends devices_1.RoomBaseDevice {
|
|
|
237
253
|
(_a = dbo_1.Persistence.dbo) === null || _a === void 0 ? void 0 : _a.persistAC(this);
|
|
238
254
|
}
|
|
239
255
|
/** @inheritDoc */
|
|
240
|
-
|
|
256
|
+
setExcessEnergyState(c) {
|
|
241
257
|
var _a, _b;
|
|
258
|
+
if (!c.on) {
|
|
259
|
+
this.setAcState(new command_1.AcSetStateCommand(c, enums_1.AcMode.Off, undefined, 'Missing excess energy'));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
242
262
|
if (this.blockAutomationHandler.automaticBlockActive) {
|
|
243
263
|
return;
|
|
244
264
|
}
|
|
245
|
-
this._activatedByExcessEnergy = true;
|
|
246
265
|
const desiredMode = this.calculateDesiredMode();
|
|
266
|
+
if (desiredMode === enums_1.AcMode.Off) {
|
|
267
|
+
// isAvailableForExcessEnergy does not cover manualDisabled or an ac-blocking energy
|
|
268
|
+
// manager, so the device can still say it wants to stay off. Leave it alone rather than
|
|
269
|
+
// forcing it on, and do not claim it was activated by excess energy.
|
|
270
|
+
this.logCommand(c, 'Excess energy offered, but the device wants to stay off', enums_1.LogDebugType.SkipUnchangedActuatorCommand);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
247
273
|
if (desiredMode === enums_1.AcMode.Cooling &&
|
|
248
274
|
this.settings.noCoolingOnMovement &&
|
|
249
275
|
((_b = (_a = this.room) === null || _a === void 0 ? void 0 : _a.PraesenzGroup) === null || _b === void 0 ? void 0 : _b.anyPresent(true))) {
|
|
250
276
|
return;
|
|
251
277
|
}
|
|
252
|
-
this.
|
|
253
|
-
this.
|
|
254
|
-
}
|
|
255
|
-
/** @inheritDoc */
|
|
256
|
-
turnOffDueToMissingEnergy() {
|
|
257
|
-
this.turnOff();
|
|
278
|
+
this._activatedByExcessEnergy = true;
|
|
279
|
+
this.setAcState(new command_1.AcSetStateCommand(c, desiredMode, undefined, 'Excess energy available'));
|
|
258
280
|
}
|
|
259
281
|
/**
|
|
260
|
-
* Sets the state of the AC
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
282
|
+
* Sets the state of the AC.
|
|
283
|
+
*
|
|
284
|
+
* Single entry point for every state change, so each one lands in the command log and
|
|
285
|
+
* the reason a unit switched can be reconstructed afterwards. Callers that represent an
|
|
286
|
+
* automatic decision pass no disableAutomaticCommand, so they do not block themselves.
|
|
287
|
+
* @param c - The command to execute
|
|
265
288
|
*/
|
|
266
|
-
|
|
267
|
-
|
|
289
|
+
setAcState(c) {
|
|
290
|
+
var _a;
|
|
291
|
+
this.logCommand(c);
|
|
292
|
+
if (c.disableAutomaticCommand) {
|
|
293
|
+
this.blockAutomationHandler.disableAutomatic(c.disableAutomaticCommand);
|
|
294
|
+
}
|
|
295
|
+
// An unset mode means "just switch it on" - which mode that is depends on season and
|
|
296
|
+
// settings, so the device resolves it rather than the caller.
|
|
297
|
+
const mode = (_a = c.mode) !== null && _a !== void 0 ? _a : (this.heatingAllowed ? enums_1.AcMode.Heating : enums_1.AcMode.Cooling);
|
|
268
298
|
this._mode = mode;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
299
|
+
// The write command chains back to this one, so the device log shows both the
|
|
300
|
+
// intent and the actual power write, mirroring the actuator path.
|
|
301
|
+
const writeCommand = new command_1.AcWriteStateToDeviceCommand(c, c.on);
|
|
302
|
+
if (c.on) {
|
|
303
|
+
this.setDesiredMode(mode, false, c.desiredTemperature);
|
|
272
304
|
}
|
|
273
|
-
this.
|
|
274
|
-
this.turnOn();
|
|
305
|
+
this.writeStateToDevice(writeCommand);
|
|
275
306
|
}
|
|
276
307
|
/** @inheritDoc */
|
|
277
308
|
wasActivatedByExcessEnergy() {
|
|
278
309
|
return this._activatedByExcessEnergy;
|
|
279
310
|
}
|
|
280
|
-
|
|
311
|
+
/**
|
|
312
|
+
* Re-evaluates what the state should be and applies it.
|
|
313
|
+
* @param c - The command asking for the re-evaluation; the resulting device command chains
|
|
314
|
+
* from it, so the log shows what triggered the change
|
|
315
|
+
*/
|
|
316
|
+
automaticCheck(c) {
|
|
281
317
|
var _a, _b;
|
|
282
318
|
if (this.blockAutomationHandler.automaticBlockActive) {
|
|
283
319
|
// We aren't allowed to turn on or off anyway --> exit
|
|
@@ -288,29 +324,57 @@ class AcDevice extends devices_1.RoomBaseDevice {
|
|
|
288
324
|
// Device already in desired state --> do nothing
|
|
289
325
|
return;
|
|
290
326
|
}
|
|
327
|
+
// Kept ahead of the branch as before: turning off still reports the mode we would
|
|
328
|
+
// otherwise have wanted, which setDesiredInfo sends alongside the power state.
|
|
291
329
|
this.setDesiredMode(desiredMode, false);
|
|
292
330
|
if (desiredMode == enums_1.AcMode.Off ||
|
|
293
331
|
(desiredMode === enums_1.AcMode.Cooling &&
|
|
294
332
|
this.settings.noCoolingOnMovement &&
|
|
295
333
|
((_b = (_a = this.room) === null || _a === void 0 ? void 0 : _a.PraesenzGroup) === null || _b === void 0 ? void 0 : _b.anyPresent(true)))) {
|
|
296
|
-
this.
|
|
334
|
+
this.setAcState(new command_1.AcSetStateCommand(c, enums_1.AcMode.Off, undefined, 'No cooling wanted'));
|
|
297
335
|
return;
|
|
298
336
|
}
|
|
299
|
-
this.
|
|
337
|
+
this.setAcState(new command_1.AcSetStateCommand(c, desiredMode, undefined, 'Desired mode reached'));
|
|
300
338
|
}
|
|
301
|
-
onRoomAnyMovement(
|
|
339
|
+
onRoomAnyMovement(action) {
|
|
302
340
|
if (!this.settings.noCoolingOnMovement || !this.on || this.mode === enums_1.AcMode.Heating) {
|
|
303
341
|
return;
|
|
304
342
|
}
|
|
305
|
-
this.
|
|
306
|
-
|
|
343
|
+
this.setAcState(new command_1.AcSetStateCommand(action, enums_1.AcMode.Off, undefined, 'Something moved in the room and noCoolingOnMovement is set.', this.buildMovementBlock(action)));
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Keeps the unit off for as long as the room counts as occupied - renewed by every movement.
|
|
347
|
+
*
|
|
348
|
+
* Without a block, staying off depended on the five-minute interval check noticing that somebody
|
|
349
|
+
* is present, and coming back on depended on the last-leave callback arriving. The block replaces
|
|
350
|
+
* both with one timer: every movement pushes it out, and its expiry reverts to automatic by
|
|
351
|
+
* itself, so the room cools again shortly after it empties rather than at the next check.
|
|
352
|
+
*
|
|
353
|
+
* The duration is the room's own movementResetTimer - the same span that decides when the room
|
|
354
|
+
* counts as empty. Anything shorter would let the unit start up with somebody still sitting there;
|
|
355
|
+
* a separate constant would be a second answer to a question the room already answers.
|
|
356
|
+
*
|
|
357
|
+
* The collision strategy is deliberately left at its default (overrideIfGreater): a long press on
|
|
358
|
+
* the wall button sets a much longer block, and walking past the unit must not cut that short.
|
|
359
|
+
* @param c - The command the block chains from, so the log shows what triggered it
|
|
360
|
+
* @returns The block, or undefined when the device has no room to take the duration from
|
|
361
|
+
*/
|
|
362
|
+
buildMovementBlock(c) {
|
|
363
|
+
var _a, _b;
|
|
364
|
+
const occupiedForSeconds = (_b = (_a = this.room) === null || _a === void 0 ? void 0 : _a.settings) === null || _b === void 0 ? void 0 : _b.movementResetTimer;
|
|
365
|
+
// No room means no answer to "how long does this count as occupied". Switching off without a
|
|
366
|
+
// block is what happened before this existed, and it is the honest fallback - a made-up
|
|
367
|
+
// duration would block the automatic for a span nothing chose.
|
|
368
|
+
if (occupiedForSeconds === undefined || occupiedForSeconds <= 0) {
|
|
369
|
+
return undefined;
|
|
370
|
+
}
|
|
371
|
+
return new command_1.BlockAutomaticCommand(c, occupiedForSeconds * 1000, 'noCoolingOnMovement', undefined, true);
|
|
307
372
|
}
|
|
308
373
|
onRoomLastLeave(action) {
|
|
309
374
|
if (!this.settings.noCoolingOnMovement) {
|
|
310
375
|
return;
|
|
311
376
|
}
|
|
312
|
-
this.
|
|
313
|
-
this.restoreTargetAutomaticValue();
|
|
377
|
+
this.restoreTargetAutomaticValue(new command_1.RestoreTargetAutomaticValueCommand(action, 'Last person left the room, whilst noCoolingOnMovement is set'));
|
|
314
378
|
}
|
|
315
379
|
/** @inheritDoc */
|
|
316
380
|
toJSON() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DaikinAC, DaikinManager } from 'daikin-controller';
|
|
2
2
|
import { AcDevice } from './ac-device';
|
|
3
|
+
import { AcWriteStateToDeviceCommand } from '../../command';
|
|
3
4
|
export declare class DaikinService {
|
|
4
5
|
private static _ownDevices;
|
|
5
6
|
private static _daikinManager;
|
|
@@ -11,7 +12,7 @@ export declare class DaikinService {
|
|
|
11
12
|
}): void;
|
|
12
13
|
static getDevice(name: string): DaikinAC | undefined;
|
|
13
14
|
static initialize(): Promise<void>;
|
|
14
|
-
static setAll(
|
|
15
|
+
static setAll(c: AcWriteStateToDeviceCommand, force?: boolean): void;
|
|
15
16
|
static reconnect(name: string, ip: string, mac?: string): Promise<DaikinAC | undefined>;
|
|
16
17
|
private static reconstructDaikinAc;
|
|
17
18
|
private static initializeDevice;
|
|
@@ -38,14 +38,14 @@ class DaikinService {
|
|
|
38
38
|
Telegram_1.TelegramService.addMessageCallback(new Telegram_1.TelegramMessageCallback('AcOn', /\/ac_on/, async (m) => {
|
|
39
39
|
if (m.from === undefined)
|
|
40
40
|
return false;
|
|
41
|
-
DaikinService.setAll(true);
|
|
41
|
+
DaikinService.setAll(new command_1.AcWriteStateToDeviceCommand(enums_1.CommandSource.Manual, true, `Telegram /ac_on by ${m.from.id}`));
|
|
42
42
|
Telegram_1.TelegramService.sendMessage([m.chat.id], 'Command executed');
|
|
43
43
|
return true;
|
|
44
44
|
}, "Turns all Ac's on without changing any settings"));
|
|
45
45
|
Telegram_1.TelegramService.addMessageCallback(new Telegram_1.TelegramMessageCallback('AcOff', /\/ac_off/, async (m) => {
|
|
46
46
|
if (m.from === undefined)
|
|
47
47
|
return false;
|
|
48
|
-
DaikinService.setAll(false, true);
|
|
48
|
+
DaikinService.setAll(new command_1.AcWriteStateToDeviceCommand(enums_1.CommandSource.Manual, false, `Telegram /ac_off by ${m.from.id}`), true);
|
|
49
49
|
Telegram_1.TelegramService.sendMessage([m.chat.id], 'Command executed');
|
|
50
50
|
return true;
|
|
51
51
|
}, "Turns all Ac's off without changing any settings"));
|
|
@@ -68,22 +68,17 @@ class DaikinService {
|
|
|
68
68
|
});
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
static setAll(on, force = false) {
|
|
71
|
+
static setAll(c, force = false) {
|
|
73
72
|
if (!this.isInitialized) {
|
|
74
73
|
return;
|
|
75
74
|
}
|
|
76
75
|
for (const deviceName in this._ownDevices) {
|
|
77
76
|
const dev = this._ownDevices[deviceName];
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
if (force) {
|
|
85
|
-
dev.blockAutomationHandler.disableAutomatic(new command_1.BlockAutomaticCommand(enums_1.CommandSource.Unknown, 180 * 60 * 1000));
|
|
86
|
-
}
|
|
77
|
+
// Contract of this method is to switch power without touching any settings, so it
|
|
78
|
+
// addresses the write layer rather than setAcState, which would resolve and apply a mode.
|
|
79
|
+
// The block is not a setting, so it travels in the command like everywhere else.
|
|
80
|
+
c.disableAutomaticCommand = force ? new command_1.BlockAutomaticCommand(c, 180 * 60 * 1000) : undefined;
|
|
81
|
+
dev.writeStateToDevice(c);
|
|
87
82
|
}
|
|
88
83
|
}
|
|
89
84
|
static async reconnect(name, ip, mac) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AcDevice } from './ac-device';
|
|
2
|
+
import { AcPerformAutomaticCheckCommand, AcWriteStateToDeviceCommand } from '../../command';
|
|
2
3
|
import { DaikinAC } from 'daikin-controller';
|
|
3
4
|
import { AcMode, DeviceType } from '../../enums';
|
|
4
5
|
export declare class OwnDaikinDevice extends AcDevice {
|
|
@@ -29,10 +30,10 @@ export declare class OwnDaikinDevice extends AcDevice {
|
|
|
29
30
|
/** @inheritDoc */
|
|
30
31
|
setDesiredMode(mode: AcMode, writeToDevice?: boolean, desiredTemp?: number): void;
|
|
31
32
|
/** @inheritDoc */
|
|
32
|
-
turnOn(): void;
|
|
33
|
+
turnOn(c: AcWriteStateToDeviceCommand): void;
|
|
33
34
|
/** @inheritDoc */
|
|
34
|
-
turnOff(): void;
|
|
35
|
-
protected automaticCheck(): void;
|
|
35
|
+
turnOff(c: AcWriteStateToDeviceCommand): void;
|
|
36
|
+
protected automaticCheck(c: AcPerformAutomaticCheckCommand): void;
|
|
36
37
|
private setDesiredInfo;
|
|
37
38
|
private updateInfo;
|
|
38
39
|
/**
|
|
@@ -77,23 +77,23 @@ class OwnDaikinDevice extends ac_device_1.AcDevice {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
/** @inheritDoc */
|
|
80
|
-
turnOn() {
|
|
81
|
-
this.
|
|
80
|
+
turnOn(c) {
|
|
81
|
+
this.logCommand(c);
|
|
82
82
|
this.desiredState = daikin_controller_1.Power.ON;
|
|
83
83
|
this.setDesiredInfo();
|
|
84
84
|
}
|
|
85
85
|
/** @inheritDoc */
|
|
86
|
-
turnOff() {
|
|
87
|
-
this.
|
|
86
|
+
turnOff(c) {
|
|
87
|
+
this.logCommand(c);
|
|
88
88
|
this._activatedByExcessEnergy = false;
|
|
89
89
|
this.desiredState = daikin_controller_1.Power.OFF;
|
|
90
90
|
this._mode = enums_1.AcMode.Off;
|
|
91
91
|
this.setDesiredInfo();
|
|
92
92
|
}
|
|
93
|
-
automaticCheck() {
|
|
93
|
+
automaticCheck(c) {
|
|
94
94
|
// First Load Device Info, then perform check
|
|
95
95
|
this.updateInfo().then((_on) => {
|
|
96
|
-
super.automaticCheck();
|
|
96
|
+
super.automaticCheck(c);
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
99
|
setDesiredInfo(retry = false, forceTemp) {
|