hoffmation-base 2.15.10 → 2.16.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/lib/server/devices/IoBrokerDeviceInfo.d.ts +2 -0
- package/lib/server/devices/IoBrokerDeviceInfo.js +11 -1
- package/lib/server/devices/deviceType.d.ts +3 -2
- package/lib/server/devices/deviceType.js +3 -2
- package/lib/server/devices/deviceUpdater.js +3 -2
- package/lib/server/devices/devices.d.ts +2 -0
- package/lib/server/devices/devices.js +25 -0
- package/lib/server/devices/index.d.ts +1 -0
- package/lib/server/devices/index.js +1 -0
- package/lib/server/devices/shelly/index.d.ts +2 -0
- package/lib/server/devices/shelly/index.js +7 -0
- package/lib/server/devices/shelly/shellyDevice.d.ts +12 -0
- package/lib/server/devices/shelly/shellyDevice.js +36 -0
- package/lib/server/devices/shelly/shellyTrv.d.ts +60 -0
- package/lib/server/devices/shelly/shellyTrv.js +267 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -9,6 +9,8 @@ export declare class IoBrokerDeviceInfo extends DeviceInfo {
|
|
|
9
9
|
channel?: number;
|
|
10
10
|
valueName?: string;
|
|
11
11
|
devConf: deviceConfig;
|
|
12
|
+
static idSplitter(id: string): string[];
|
|
13
|
+
private static replaceInvalidIdChars;
|
|
12
14
|
/**
|
|
13
15
|
* Extracts the relevant infos from the passed deviceConfig and combines them in a new Info object
|
|
14
16
|
* @param {deviceConfig} pDevConf The device Config based on the extracted devices.json from ioBroker
|
|
@@ -7,6 +7,16 @@ exports.IoBrokerDeviceInfo = void 0;
|
|
|
7
7
|
const lodash_1 = __importDefault(require("lodash"));
|
|
8
8
|
const DeviceInfo_1 = require("./DeviceInfo");
|
|
9
9
|
class IoBrokerDeviceInfo extends DeviceInfo_1.DeviceInfo {
|
|
10
|
+
static idSplitter(id) {
|
|
11
|
+
const split = id.split('.');
|
|
12
|
+
if (split[2] !== undefined) {
|
|
13
|
+
split[2] = this.replaceInvalidIdChars(split[2]);
|
|
14
|
+
}
|
|
15
|
+
return split;
|
|
16
|
+
}
|
|
17
|
+
static replaceInvalidIdChars(idPart) {
|
|
18
|
+
return idPart.replace(/[#\-]/g, '_');
|
|
19
|
+
}
|
|
10
20
|
/**
|
|
11
21
|
* Extracts the relevant infos from the passed deviceConfig and combines them in a new Info object
|
|
12
22
|
* @param {deviceConfig} pDevConf The device Config based on the extracted devices.json from ioBroker
|
|
@@ -17,7 +27,7 @@ class IoBrokerDeviceInfo extends DeviceInfo_1.DeviceInfo {
|
|
|
17
27
|
super();
|
|
18
28
|
this.devConf = pDevConf;
|
|
19
29
|
this.type = pDevConf.type;
|
|
20
|
-
const idSplit = pDevConf._id
|
|
30
|
+
const idSplit = IoBrokerDeviceInfo.idSplitter(pDevConf._id);
|
|
21
31
|
this.fullID = pDevConf._id;
|
|
22
32
|
this.devID = idSplit[2];
|
|
23
33
|
this.fullName = pDevConf.common.name;
|
|
@@ -36,10 +36,11 @@ export declare enum DeviceType {
|
|
|
36
36
|
ZigbeeOsramDimmer = 222,
|
|
37
37
|
ZigbeeIkeaShutter = 223,
|
|
38
38
|
ZigbeeUbisysActuator = 224,
|
|
39
|
-
ZigbeeUbisysLampe =
|
|
40
|
-
ZigbeeInnr142C =
|
|
39
|
+
ZigbeeUbisysLampe = 225,
|
|
40
|
+
ZigbeeInnr142C = 226,
|
|
41
41
|
JsEnergyManager = 301,
|
|
42
42
|
RoomScene = 401,
|
|
43
|
+
ShellyTrv = 402,
|
|
43
44
|
WledDevice = 1001,
|
|
44
45
|
Daikin = 2001,
|
|
45
46
|
Sonos = 3001,
|
|
@@ -40,10 +40,11 @@ var DeviceType;
|
|
|
40
40
|
DeviceType[DeviceType["ZigbeeOsramDimmer"] = 222] = "ZigbeeOsramDimmer";
|
|
41
41
|
DeviceType[DeviceType["ZigbeeIkeaShutter"] = 223] = "ZigbeeIkeaShutter";
|
|
42
42
|
DeviceType[DeviceType["ZigbeeUbisysActuator"] = 224] = "ZigbeeUbisysActuator";
|
|
43
|
-
DeviceType[DeviceType["ZigbeeUbisysLampe"] =
|
|
44
|
-
DeviceType[DeviceType["ZigbeeInnr142C"] =
|
|
43
|
+
DeviceType[DeviceType["ZigbeeUbisysLampe"] = 225] = "ZigbeeUbisysLampe";
|
|
44
|
+
DeviceType[DeviceType["ZigbeeInnr142C"] = 226] = "ZigbeeInnr142C";
|
|
45
45
|
DeviceType[DeviceType["JsEnergyManager"] = 301] = "JsEnergyManager";
|
|
46
46
|
DeviceType[DeviceType["RoomScene"] = 401] = "RoomScene";
|
|
47
|
+
DeviceType[DeviceType["ShellyTrv"] = 402] = "ShellyTrv";
|
|
47
48
|
DeviceType[DeviceType["WledDevice"] = 1001] = "WledDevice";
|
|
48
49
|
DeviceType[DeviceType["Daikin"] = 2001] = "Daikin";
|
|
49
50
|
DeviceType[DeviceType["Sonos"] = 3001] = "Sonos";
|
|
@@ -5,12 +5,13 @@ const services_1 = require("../services");
|
|
|
5
5
|
const models_1 = require("../../models");
|
|
6
6
|
const devices_1 = require("./devices");
|
|
7
7
|
const mqtt_1 = require("./mqtt");
|
|
8
|
+
const IoBrokerDeviceInfo_1 = require("./IoBrokerDeviceInfo");
|
|
8
9
|
class DeviceUpdater {
|
|
9
10
|
constructor(pDevices) {
|
|
10
11
|
this.devices = pDevices;
|
|
11
12
|
}
|
|
12
13
|
updateObject(pId, pObj) {
|
|
13
|
-
const idSplit =
|
|
14
|
+
const idSplit = IoBrokerDeviceInfo_1.IoBrokerDeviceInfo.idSplitter(pId);
|
|
14
15
|
if (idSplit.length < 2)
|
|
15
16
|
return;
|
|
16
17
|
if (idSplit[0] === devices_1.Devices.IDENTIFIER_HOMEMATIC) {
|
|
@@ -23,7 +24,7 @@ class DeviceUpdater {
|
|
|
23
24
|
// Ignore null states
|
|
24
25
|
return;
|
|
25
26
|
}
|
|
26
|
-
const idSplit =
|
|
27
|
+
const idSplit = IoBrokerDeviceInfo_1.IoBrokerDeviceInfo.idSplitter(id);
|
|
27
28
|
if (idSplit.length < 2)
|
|
28
29
|
return;
|
|
29
30
|
if (idSplit[0] == 'mqtt') {
|
|
@@ -5,6 +5,7 @@ import { iConfig } from '../config';
|
|
|
5
5
|
export declare class Devices {
|
|
6
6
|
static IDENTIFIER_HOMEMATIC: string;
|
|
7
7
|
static IDENTIFIER_JS: string;
|
|
8
|
+
static IDENTIFIER_Shelly: string;
|
|
8
9
|
static IDENTIFIER_ZIGBEE: string;
|
|
9
10
|
static IDENTIFIER_WLED: string;
|
|
10
11
|
static alLDevices: {
|
|
@@ -19,6 +20,7 @@ export declare class Devices {
|
|
|
19
20
|
static midnightReset(): void;
|
|
20
21
|
static resetDetectionsToday(): void;
|
|
21
22
|
static getBatteryInfo(): string;
|
|
23
|
+
private static processShellyDevice;
|
|
22
24
|
private static processZigbeeDevice;
|
|
23
25
|
private static processWledDevice;
|
|
24
26
|
private static processHMIPDevice;
|
|
@@ -10,6 +10,7 @@ const IoBrokerDeviceInfo_1 = require("./IoBrokerDeviceInfo");
|
|
|
10
10
|
const jsObject_1 = require("./jsObject");
|
|
11
11
|
const wledDevice_1 = require("./wledDevice");
|
|
12
12
|
const DeviceCapability_1 = require("./DeviceCapability");
|
|
13
|
+
const shelly_1 = require("./shelly");
|
|
13
14
|
class Devices {
|
|
14
15
|
constructor(pDeviceData, pRoomImportEnforcer, config) {
|
|
15
16
|
var _a;
|
|
@@ -35,6 +36,9 @@ class Devices {
|
|
|
35
36
|
else if (cName.indexOf('00-WLED') === 0) {
|
|
36
37
|
Devices.processWledDevice(cDevConf);
|
|
37
38
|
}
|
|
39
|
+
else if (cName.indexOf('00-Shelly') === 0) {
|
|
40
|
+
Devices.processShellyDevice(cDevConf);
|
|
41
|
+
}
|
|
38
42
|
else if (cName.indexOf('00-EnergyManager') === 0 &&
|
|
39
43
|
cDevConf.type !== 'folder' &&
|
|
40
44
|
!((_a = config === null || config === void 0 ? void 0 : config.energyManager) === null || _a === void 0 ? void 0 : _a.disableJsEnergyManager)) {
|
|
@@ -44,6 +48,7 @@ class Devices {
|
|
|
44
48
|
}
|
|
45
49
|
hmIPDevices_1.HmIPDevice.checkMissing();
|
|
46
50
|
zigbee_1.ZigbeeDevice.checkMissing();
|
|
51
|
+
shelly_1.ShellyDevice.checkMissing();
|
|
47
52
|
}
|
|
48
53
|
static midnightReset() {
|
|
49
54
|
// Nothing yet
|
|
@@ -81,6 +86,25 @@ class Devices {
|
|
|
81
86
|
}
|
|
82
87
|
return result.join('\n');
|
|
83
88
|
}
|
|
89
|
+
static processShellyDevice(cDevConf) {
|
|
90
|
+
const shellyInfo = new IoBrokerDeviceInfo_1.IoBrokerDeviceInfo(cDevConf);
|
|
91
|
+
const fullName = `${Devices.IDENTIFIER_Shelly}-${shellyInfo.devID}`;
|
|
92
|
+
shellyInfo.allDevicesKey = fullName;
|
|
93
|
+
if (typeof Devices.alLDevices[fullName] !== 'undefined') {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
services_1.ServerLogService.writeLog(models_1.LogLevel.Trace, `Shelly ${shellyInfo.devID} with Type "${shellyInfo.deviceType}" doesn't exists --> create it`);
|
|
97
|
+
let d;
|
|
98
|
+
switch (shellyInfo.deviceType) {
|
|
99
|
+
case 'Trv':
|
|
100
|
+
d = new shelly_1.ShellyTrv(shellyInfo);
|
|
101
|
+
break;
|
|
102
|
+
default:
|
|
103
|
+
services_1.ServerLogService.writeLog(models_1.LogLevel.Warn, `No shelly Device Type for ${shellyInfo.deviceType} defined`);
|
|
104
|
+
d = new shelly_1.ShellyDevice(shellyInfo, deviceType_1.DeviceType.unknown);
|
|
105
|
+
}
|
|
106
|
+
Devices.alLDevices[fullName] = d;
|
|
107
|
+
}
|
|
84
108
|
static processZigbeeDevice(cDevConf) {
|
|
85
109
|
const zigbeeInfo = new IoBrokerDeviceInfo_1.IoBrokerDeviceInfo(cDevConf);
|
|
86
110
|
const fullName = `${Devices.IDENTIFIER_ZIGBEE}-${zigbeeInfo.devID}`;
|
|
@@ -249,6 +273,7 @@ class Devices {
|
|
|
249
273
|
exports.Devices = Devices;
|
|
250
274
|
Devices.IDENTIFIER_HOMEMATIC = 'hm-rpc';
|
|
251
275
|
Devices.IDENTIFIER_JS = 'javascript';
|
|
276
|
+
Devices.IDENTIFIER_Shelly = 'shelly';
|
|
252
277
|
Devices.IDENTIFIER_ZIGBEE = 'zigbee';
|
|
253
278
|
Devices.IDENTIFIER_WLED = 'wled';
|
|
254
279
|
Devices.alLDevices = {};
|
|
@@ -7,6 +7,7 @@ export * from './hmIPDevices/index';
|
|
|
7
7
|
export * from './jsObject/index';
|
|
8
8
|
export * from './models/index';
|
|
9
9
|
export * from './scene/index';
|
|
10
|
+
export * from './shelly/index';
|
|
10
11
|
export * from './zigbee/index';
|
|
11
12
|
export * from './device-cluster';
|
|
12
13
|
export * from './device-cluster-type';
|
|
@@ -23,6 +23,7 @@ __exportStar(require("./hmIPDevices/index"), exports);
|
|
|
23
23
|
__exportStar(require("./jsObject/index"), exports);
|
|
24
24
|
__exportStar(require("./models/index"), exports);
|
|
25
25
|
__exportStar(require("./scene/index"), exports);
|
|
26
|
+
__exportStar(require("./shelly/index"), exports);
|
|
26
27
|
__exportStar(require("./zigbee/index"), exports);
|
|
27
28
|
__exportStar(require("./device-cluster"), exports);
|
|
28
29
|
__exportStar(require("./device-cluster-type"), exports);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ShellyTrv = exports.ShellyDevice = void 0;
|
|
4
|
+
var shellyDevice_1 = require("./shellyDevice");
|
|
5
|
+
Object.defineProperty(exports, "ShellyDevice", { enumerable: true, get: function () { return shellyDevice_1.ShellyDevice; } });
|
|
6
|
+
var shellyTrv_1 = require("./shellyTrv");
|
|
7
|
+
Object.defineProperty(exports, "ShellyTrv", { enumerable: true, get: function () { return shellyTrv_1.ShellyTrv; } });
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IoBrokerBaseDevice } from '../IoBrokerBaseDevice';
|
|
2
|
+
import { iDisposable } from '../../services';
|
|
3
|
+
import { IoBrokerDeviceInfo } from '../IoBrokerDeviceInfo';
|
|
4
|
+
import { DeviceType } from '../deviceType';
|
|
5
|
+
export declare class ShellyDevice extends IoBrokerBaseDevice implements iDisposable {
|
|
6
|
+
private _lastUpdate;
|
|
7
|
+
get lastUpdate(): Date;
|
|
8
|
+
stateMap: Map<string, ioBroker.State>;
|
|
9
|
+
constructor(pInfo: IoBrokerDeviceInfo, pType: DeviceType);
|
|
10
|
+
update(idSplit: string[], state: ioBroker.State, initial?: boolean, pOverride?: boolean): void;
|
|
11
|
+
dispose(): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ShellyDevice = void 0;
|
|
4
|
+
const IoBrokerBaseDevice_1 = require("../IoBrokerBaseDevice");
|
|
5
|
+
const models_1 = require("../../../models");
|
|
6
|
+
class ShellyDevice extends IoBrokerBaseDevice_1.IoBrokerBaseDevice {
|
|
7
|
+
get lastUpdate() {
|
|
8
|
+
return this._lastUpdate;
|
|
9
|
+
}
|
|
10
|
+
constructor(pInfo, pType) {
|
|
11
|
+
super(pInfo, pType);
|
|
12
|
+
this._lastUpdate = new Date(0);
|
|
13
|
+
this.stateMap = new Map();
|
|
14
|
+
}
|
|
15
|
+
update(idSplit, state, initial = false, pOverride = false) {
|
|
16
|
+
this.log(models_1.LogLevel.DeepTrace, `Shelly: ${initial ? 'Initiales ' : ''}Update: ID: ${idSplit.join('.')} JSON: ${JSON.stringify(state)}`);
|
|
17
|
+
if (!pOverride) {
|
|
18
|
+
this.log(models_1.LogLevel.Warn, `Keine Update Überschreibung:\n\tID: ${idSplit.join('.')}\n\tData: ${JSON.stringify(state)}`);
|
|
19
|
+
}
|
|
20
|
+
const stateLastUpdate = new Date(state.ts);
|
|
21
|
+
if (stateLastUpdate > this._lastUpdate) {
|
|
22
|
+
this._lastUpdate = stateLastUpdate;
|
|
23
|
+
}
|
|
24
|
+
this.stateMap.set(idSplit[3], state);
|
|
25
|
+
const individualCallbacks = this.individualStateCallbacks.get(idSplit[3]);
|
|
26
|
+
if (individualCallbacks !== undefined) {
|
|
27
|
+
for (const cb of individualCallbacks) {
|
|
28
|
+
cb(state.val);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
dispose() {
|
|
33
|
+
// Nothing yet
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.ShellyDevice = ShellyDevice;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ShellyDevice } from './shellyDevice';
|
|
3
|
+
import { iHeater } from '../baseDeviceInterfaces';
|
|
4
|
+
import { HeaterSettings } from '../../../models';
|
|
5
|
+
import { IoBrokerDeviceInfo } from '../IoBrokerDeviceInfo';
|
|
6
|
+
export declare class ShellyTrv extends ShellyDevice implements iHeater {
|
|
7
|
+
settings: HeaterSettings;
|
|
8
|
+
get lastBatteryPersist(): number;
|
|
9
|
+
readonly persistHeaterInterval: NodeJS.Timeout;
|
|
10
|
+
get battery(): number;
|
|
11
|
+
private _automaticMode;
|
|
12
|
+
private _battery;
|
|
13
|
+
private _iAutomaticInterval;
|
|
14
|
+
private _initialSeasonCheckDone;
|
|
15
|
+
private _lastRecalc;
|
|
16
|
+
private _level;
|
|
17
|
+
private _recalcTimeout;
|
|
18
|
+
private _temperatur;
|
|
19
|
+
private _targetTempVal;
|
|
20
|
+
private _desiredTemperatur;
|
|
21
|
+
private _useExternalTemperatureEnabled;
|
|
22
|
+
private _pidController;
|
|
23
|
+
private _lastBatteryPersist;
|
|
24
|
+
private readonly _batteryId;
|
|
25
|
+
private readonly _setAutomaticModeId;
|
|
26
|
+
private readonly _setExternalTempId;
|
|
27
|
+
private readonly _setEnableExternalTempId;
|
|
28
|
+
private readonly _setPointTemperaturID;
|
|
29
|
+
private readonly _temperatureId;
|
|
30
|
+
private readonly _valvePosId;
|
|
31
|
+
constructor(pInfo: IoBrokerDeviceInfo);
|
|
32
|
+
protected _seasonTurnOff: boolean;
|
|
33
|
+
get seasonTurnOff(): boolean;
|
|
34
|
+
set seasonTurnOff(value: boolean);
|
|
35
|
+
get desiredTemperature(): number;
|
|
36
|
+
set desiredTemperature(val: number);
|
|
37
|
+
protected _humidity: number;
|
|
38
|
+
get humidity(): number;
|
|
39
|
+
get sLevel(): string;
|
|
40
|
+
get iLevel(): number;
|
|
41
|
+
get sTemperatur(): string;
|
|
42
|
+
get iTemperature(): number;
|
|
43
|
+
protected _roomTemperature: number;
|
|
44
|
+
get roomTemperature(): number;
|
|
45
|
+
set roomTemperatur(val: number);
|
|
46
|
+
checkAutomaticChange(): void;
|
|
47
|
+
stopAutomaticCheck(): void;
|
|
48
|
+
onTemperaturChange(newTemperatur: number): void;
|
|
49
|
+
persistHeater(): void;
|
|
50
|
+
update(idSplit: string[], state: ioBroker.State, initial?: boolean): void;
|
|
51
|
+
protected getNextPidLevel(): number;
|
|
52
|
+
private checkSeasonTurnOff;
|
|
53
|
+
persistBatteryDevice(): void;
|
|
54
|
+
dispose(): void;
|
|
55
|
+
recalcLevel(): void;
|
|
56
|
+
private setMode;
|
|
57
|
+
private setExternalTemperature;
|
|
58
|
+
private setExternalTemperatureEnabled;
|
|
59
|
+
private setValve;
|
|
60
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ShellyTrv = void 0;
|
|
4
|
+
const shellyDevice_1 = require("./shellyDevice");
|
|
5
|
+
const baseDeviceInterfaces_1 = require("../baseDeviceInterfaces");
|
|
6
|
+
const services_1 = require("../../services");
|
|
7
|
+
const models_1 = require("../../../models");
|
|
8
|
+
const liquid_pid_1 = require("../../../liquid-pid");
|
|
9
|
+
const deviceType_1 = require("../deviceType");
|
|
10
|
+
const DeviceCapability_1 = require("../DeviceCapability");
|
|
11
|
+
class ShellyTrv extends shellyDevice_1.ShellyDevice {
|
|
12
|
+
get lastBatteryPersist() {
|
|
13
|
+
return this._lastBatteryPersist;
|
|
14
|
+
}
|
|
15
|
+
get battery() {
|
|
16
|
+
return this._battery;
|
|
17
|
+
}
|
|
18
|
+
constructor(pInfo) {
|
|
19
|
+
super(pInfo, deviceType_1.DeviceType.ShellyTrv);
|
|
20
|
+
this.settings = new models_1.HeaterSettings();
|
|
21
|
+
this.persistHeaterInterval = services_1.Utils.guardedInterval(() => {
|
|
22
|
+
this.persistHeater();
|
|
23
|
+
}, 5 * 60 * 1000, this, false);
|
|
24
|
+
this._automaticMode = false;
|
|
25
|
+
this._battery = -99;
|
|
26
|
+
this._initialSeasonCheckDone = false;
|
|
27
|
+
this._lastRecalc = 0;
|
|
28
|
+
this._level = 0;
|
|
29
|
+
this._recalcTimeout = null;
|
|
30
|
+
this._temperatur = baseDeviceInterfaces_1.UNDEFINED_TEMP_VALUE;
|
|
31
|
+
this._targetTempVal = baseDeviceInterfaces_1.UNDEFINED_TEMP_VALUE;
|
|
32
|
+
this._desiredTemperatur = baseDeviceInterfaces_1.UNDEFINED_TEMP_VALUE;
|
|
33
|
+
this._useExternalTemperatureEnabled = false;
|
|
34
|
+
this._pidController = new liquid_pid_1.PIDController({
|
|
35
|
+
temp: {
|
|
36
|
+
ref: 20, // Point temperature
|
|
37
|
+
},
|
|
38
|
+
Pmax: 100,
|
|
39
|
+
// Tune the PID Controller
|
|
40
|
+
Kp: 25,
|
|
41
|
+
Ki: 1000,
|
|
42
|
+
Kd: 9, // PID: Kd in 1/1000
|
|
43
|
+
});
|
|
44
|
+
this._lastBatteryPersist = 0;
|
|
45
|
+
this._seasonTurnOff = false;
|
|
46
|
+
this._humidity = 0;
|
|
47
|
+
this._roomTemperature = baseDeviceInterfaces_1.UNDEFINED_TEMP_VALUE;
|
|
48
|
+
this.deviceCapabilities.push(DeviceCapability_1.DeviceCapability.heater);
|
|
49
|
+
this.deviceCapabilities.push(DeviceCapability_1.DeviceCapability.batteryDriven);
|
|
50
|
+
this._batteryId = `${this.info.fullID}.bat.value`;
|
|
51
|
+
this._setAutomaticModeId = `${this.info.fullID}.tmp.automaticTemperatureControl`;
|
|
52
|
+
this._setExternalTempId = `${this.info.fullID}.ext.temperature`;
|
|
53
|
+
this._setEnableExternalTempId = `${this.info.fullID}.ext.enabled`;
|
|
54
|
+
this._setPointTemperaturID = `${this.info.fullID}.tmp.temperatureC`;
|
|
55
|
+
this._temperatureId = `${this.info.fullID}.tmp.valvePosition`;
|
|
56
|
+
this._valvePosId = `${this.info.fullID}.tmp.valvePosition`;
|
|
57
|
+
this._iAutomaticInterval = services_1.Utils.guardedInterval(this.checkAutomaticChange, 300000, this); // Alle 5 Minuten prüfen
|
|
58
|
+
services_1.TimeCallbackService.addCallback(new models_1.TimeCallback(`${this.info.fullID} Season Check`, models_1.TimeCallbackType.TimeOfDay, () => {
|
|
59
|
+
this.checkSeasonTurnOff();
|
|
60
|
+
}, 0, 2, 0));
|
|
61
|
+
}
|
|
62
|
+
get seasonTurnOff() {
|
|
63
|
+
return this._seasonTurnOff;
|
|
64
|
+
}
|
|
65
|
+
set seasonTurnOff(value) {
|
|
66
|
+
this._seasonTurnOff = value;
|
|
67
|
+
if (value) {
|
|
68
|
+
this.setMode(false);
|
|
69
|
+
this.setValve(0);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.setMode(!this.settings.controlByPid);
|
|
73
|
+
}
|
|
74
|
+
get desiredTemperature() {
|
|
75
|
+
return this._desiredTemperatur;
|
|
76
|
+
}
|
|
77
|
+
set desiredTemperature(val) {
|
|
78
|
+
this._desiredTemperatur = val;
|
|
79
|
+
if (this._targetTempVal === val) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
this.setState(this._setPointTemperaturID, val, () => {
|
|
83
|
+
this.log(models_1.LogLevel.Info, `Changed temperature of to "${val}.`);
|
|
84
|
+
}, (err) => {
|
|
85
|
+
this.log(models_1.LogLevel.Error, `Temperaturänderung ergab Fehler ${err}.`);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
get humidity() {
|
|
89
|
+
return this._humidity;
|
|
90
|
+
}
|
|
91
|
+
get sLevel() {
|
|
92
|
+
return `${this._level * 100}%`;
|
|
93
|
+
}
|
|
94
|
+
get iLevel() {
|
|
95
|
+
return this._level;
|
|
96
|
+
}
|
|
97
|
+
get sTemperatur() {
|
|
98
|
+
return `${this.iTemperature}°C`;
|
|
99
|
+
}
|
|
100
|
+
get iTemperature() {
|
|
101
|
+
if (this.settings.useOwnTemperatur) {
|
|
102
|
+
return this._temperatur;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
return this._roomTemperature;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
get roomTemperature() {
|
|
109
|
+
return this._roomTemperature;
|
|
110
|
+
}
|
|
111
|
+
set roomTemperatur(val) {
|
|
112
|
+
this._roomTemperature = val;
|
|
113
|
+
if (this.settings.useOwnTemperatur) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
this.setExternalTemperature(val);
|
|
117
|
+
if (this.settings.controlByPid) {
|
|
118
|
+
this.recalcLevel();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
checkAutomaticChange() {
|
|
122
|
+
var _a, _b, _c, _d, _e, _f;
|
|
123
|
+
if (!this._initialSeasonCheckDone) {
|
|
124
|
+
this.checkSeasonTurnOff();
|
|
125
|
+
}
|
|
126
|
+
if (this.seasonTurnOff) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (!this.settings.useOwnTemperatur && !this.settings.controlByPid) {
|
|
130
|
+
this.setExternalTemperatureEnabled(true);
|
|
131
|
+
}
|
|
132
|
+
const heatGroupSettings = (_b = (_a = this.room) === null || _a === void 0 ? void 0 : _a.HeatGroup) === null || _b === void 0 ? void 0 : _b.settings;
|
|
133
|
+
if ((heatGroupSettings === null || heatGroupSettings === void 0 ? void 0 : heatGroupSettings.automaticMode) == false) {
|
|
134
|
+
this.desiredTemperature = heatGroupSettings.manualTemperature;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (!this.settings.automaticMode) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const setting = models_1.TemperatureSettings.getActiveSetting((_f = (_e = (_d = (_c = this.room) === null || _c === void 0 ? void 0 : _c.HeatGroup) === null || _d === void 0 ? void 0 : _d.settings) === null || _e === void 0 ? void 0 : _e.automaticPoints) !== null && _f !== void 0 ? _f : [], new Date());
|
|
141
|
+
if (setting === undefined) {
|
|
142
|
+
this.log(models_1.LogLevel.Warn, `Undefined Heating Timestamp.`);
|
|
143
|
+
this.desiredTemperature = this.settings.automaticFallBackTemperatur;
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (this._desiredTemperatur !== setting.temperature) {
|
|
147
|
+
this.log(models_1.LogLevel.Debug, `Automatische Temperaturanpassung für ${this.info.customName} auf ${setting.temperature}°C`);
|
|
148
|
+
this.desiredTemperature = setting.temperature;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
stopAutomaticCheck() {
|
|
152
|
+
if (this._iAutomaticInterval !== undefined) {
|
|
153
|
+
clearInterval(this._iAutomaticInterval);
|
|
154
|
+
this._iAutomaticInterval = undefined;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
onTemperaturChange(newTemperatur) {
|
|
158
|
+
this.roomTemperatur = newTemperatur;
|
|
159
|
+
}
|
|
160
|
+
persistHeater() {
|
|
161
|
+
var _a;
|
|
162
|
+
(_a = services_1.Utils.dbo) === null || _a === void 0 ? void 0 : _a.persistHeater(this);
|
|
163
|
+
}
|
|
164
|
+
update(idSplit, state, initial = false) {
|
|
165
|
+
const fullId = idSplit.join('.');
|
|
166
|
+
switch (fullId) {
|
|
167
|
+
case this._valvePosId:
|
|
168
|
+
this.log(models_1.LogLevel.Trace, `Valve position update for ${this.info.customName} to "${state.val}"`);
|
|
169
|
+
this._level = state.val / 100;
|
|
170
|
+
break;
|
|
171
|
+
case this._setEnableExternalTempId:
|
|
172
|
+
this._useExternalTemperatureEnabled = state.val;
|
|
173
|
+
break;
|
|
174
|
+
case this._temperatureId:
|
|
175
|
+
this._temperatur = state.val;
|
|
176
|
+
break;
|
|
177
|
+
case this._setAutomaticModeId:
|
|
178
|
+
this._automaticMode = state.val;
|
|
179
|
+
const desiredMode = !this.settings.controlByPid;
|
|
180
|
+
if (this._automaticMode !== desiredMode) {
|
|
181
|
+
this.setMode(desiredMode);
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
184
|
+
case this._setPointTemperaturID:
|
|
185
|
+
this._targetTempVal = state.val;
|
|
186
|
+
break;
|
|
187
|
+
case this._batteryId:
|
|
188
|
+
this._battery = state.val;
|
|
189
|
+
this.persistBatteryDevice();
|
|
190
|
+
if (this._battery < 20) {
|
|
191
|
+
this.log(models_1.LogLevel.Warn, `Das Shelly Gerät hat unter 20% Batterie.`);
|
|
192
|
+
}
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
super.update(idSplit, state, initial, true);
|
|
196
|
+
}
|
|
197
|
+
getNextPidLevel() {
|
|
198
|
+
if (this.seasonTurnOff || this._roomTemperature < 0) {
|
|
199
|
+
return 0;
|
|
200
|
+
}
|
|
201
|
+
this._pidController.setPoint(this.desiredTemperature);
|
|
202
|
+
const newValue = this._pidController.calculate(this._roomTemperature);
|
|
203
|
+
this.log(models_1.LogLevel.Debug, `New PID Value ${newValue}% (cTemp: ${this._roomTemperature}, dTemp: ${this.desiredTemperature})`);
|
|
204
|
+
return newValue;
|
|
205
|
+
}
|
|
206
|
+
checkSeasonTurnOff() {
|
|
207
|
+
const desiredState = services_1.Utils.beetweenDays(new Date(), this.settings.seasonTurnOffDay, this.settings.seasonTurnOnDay);
|
|
208
|
+
if (desiredState !== this.seasonTurnOff || !this._initialSeasonCheckDone) {
|
|
209
|
+
this.log(models_1.LogLevel.Info, `Switching Seasonal Heating --> New seasonTurnOff: ${desiredState}`);
|
|
210
|
+
this.seasonTurnOff = desiredState;
|
|
211
|
+
}
|
|
212
|
+
this._initialSeasonCheckDone = true;
|
|
213
|
+
}
|
|
214
|
+
persistBatteryDevice() {
|
|
215
|
+
var _a;
|
|
216
|
+
const now = services_1.Utils.nowMS();
|
|
217
|
+
if (this._lastBatteryPersist + 60000 > now) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
(_a = services_1.Utils.dbo) === null || _a === void 0 ? void 0 : _a.persistBatteryDevice(this);
|
|
221
|
+
this._lastBatteryPersist = now;
|
|
222
|
+
}
|
|
223
|
+
dispose() {
|
|
224
|
+
if (this.persistHeaterInterval) {
|
|
225
|
+
clearInterval(this.persistHeaterInterval);
|
|
226
|
+
}
|
|
227
|
+
if (this._iAutomaticInterval) {
|
|
228
|
+
clearInterval(this._iAutomaticInterval);
|
|
229
|
+
this._iAutomaticInterval = undefined;
|
|
230
|
+
}
|
|
231
|
+
super.dispose();
|
|
232
|
+
}
|
|
233
|
+
recalcLevel() {
|
|
234
|
+
if (this.settings.useOwnTemperatur || this.seasonTurnOff || !this.settings.controlByPid) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const msTilNextMinimumCheck = this._lastRecalc + 5 * 60 * 1000 - services_1.Utils.nowMS();
|
|
238
|
+
if (msTilNextMinimumCheck > 0) {
|
|
239
|
+
if (this._recalcTimeout == null) {
|
|
240
|
+
this._recalcTimeout = services_1.Utils.guardedTimeout(this.recalcLevel, msTilNextMinimumCheck, this);
|
|
241
|
+
}
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
this.setValve(Math.max(this.getNextPidLevel(), this.settings.pidForcedMinimum));
|
|
245
|
+
}
|
|
246
|
+
setMode(automatic) {
|
|
247
|
+
this.setState(this._setAutomaticModeId, automatic);
|
|
248
|
+
}
|
|
249
|
+
setExternalTemperature(value) {
|
|
250
|
+
this.setState(this._setExternalTempId, value);
|
|
251
|
+
}
|
|
252
|
+
setExternalTemperatureEnabled(value) {
|
|
253
|
+
if (value === this._useExternalTemperatureEnabled) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
this.setState(this._setEnableExternalTempId, value);
|
|
257
|
+
}
|
|
258
|
+
setValve(target) {
|
|
259
|
+
if (target == this._level) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
this._level = target;
|
|
263
|
+
this.log(models_1.LogLevel.Info, `Setting Valve to new value: "${target}%"`);
|
|
264
|
+
this.setState(this._valvePosId, target);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
exports.ShellyTrv = ShellyTrv;
|