hoffmation-base 3.8.0 → 4.1.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/action/index.d.ts +1 -0
- package/lib/action/index.js +3 -1
- package/lib/action/soilSensorChangeAction.d.ts +16 -0
- package/lib/action/soilSensorChangeAction.js +15 -0
- package/lib/devices/dachs/dachs.d.ts +79 -2
- package/lib/devices/dachs/dachs.js +214 -18
- package/lib/devices/device-cluster.js +7 -0
- package/lib/devices/devices.d.ts +36 -1
- package/lib/devices/devices.js +67 -0
- package/lib/devices/jsObject/jsObjectEnergyManager.d.ts +16 -1
- package/lib/devices/jsObject/jsObjectEnergyManager.js +23 -0
- package/lib/devices/sharedFunctions/index.d.ts +1 -0
- package/lib/devices/sharedFunctions/index.js +1 -0
- package/lib/devices/sharedFunctions/soilSensor.d.ts +23 -0
- package/lib/devices/sharedFunctions/soilSensor.js +58 -0
- package/lib/devices/victron/victron-device.d.ts +83 -1
- package/lib/devices/victron/victron-device.js +151 -2
- package/lib/devices/victron/victron-morning-release.d.ts +16 -0
- package/lib/devices/victron/victron-morning-release.js +2 -0
- package/lib/devices/zigbee/BaseDevices/index.d.ts +1 -0
- package/lib/devices/zigbee/BaseDevices/index.js +1 -0
- package/lib/devices/zigbee/BaseDevices/zigbeeSoilSensor.d.ts +33 -0
- package/lib/devices/zigbee/BaseDevices/zigbeeSoilSensor.js +62 -0
- package/lib/devices/zigbee/index.d.ts +1 -0
- package/lib/devices/zigbee/index.js +1 -0
- package/lib/devices/zigbee/zigbeeCooloSoilSensor.d.ts +44 -0
- package/lib/devices/zigbee/zigbeeCooloSoilSensor.js +81 -0
- package/lib/enums/DeviceCapability.d.ts +2 -0
- package/lib/enums/DeviceCapability.js +2 -0
- package/lib/enums/commandType.d.ts +1 -0
- package/lib/enums/commandType.js +1 -0
- package/lib/enums/device-cluster-type.d.ts +2 -1
- package/lib/enums/device-cluster-type.js +1 -0
- package/lib/enums/deviceType.d.ts +1 -0
- package/lib/enums/deviceType.js +1 -0
- package/lib/interfaces/baseDevices/iAirQualityCollector.d.ts +2 -1
- package/lib/interfaces/baseDevices/iAirQualityReadings.d.ts +50 -0
- package/lib/interfaces/baseDevices/iAirQualityReadings.js +2 -0
- package/lib/interfaces/baseDevices/iAirQualitySensor.d.ts +1 -54
- package/lib/interfaces/baseDevices/iAirQualitySensor.js +0 -5
- package/lib/interfaces/baseDevices/iEnergyManager.d.ts +43 -0
- package/lib/interfaces/baseDevices/iHumidityCollector.d.ts +0 -1
- package/lib/interfaces/baseDevices/iHumidityCollector.js +0 -2
- package/lib/interfaces/baseDevices/iSoilCollector.d.ts +23 -0
- package/lib/interfaces/baseDevices/iSoilCollector.js +2 -0
- package/lib/interfaces/baseDevices/iSoilSensor.d.ts +32 -0
- package/lib/interfaces/baseDevices/iSoilSensor.js +2 -0
- package/lib/interfaces/baseDevices/iTemperatureCollector.d.ts +0 -1
- package/lib/interfaces/baseDevices/iTemperatureCollector.js +0 -2
- package/lib/interfaces/baseDevices/index.d.ts +7 -0
- package/lib/interfaces/baseDevices/index.js +7 -0
- package/lib/interfaces/baseDevices/undefinedAirQualityValue.d.ts +4 -0
- package/lib/interfaces/baseDevices/undefinedAirQualityValue.js +7 -0
- package/lib/interfaces/baseDevices/undefinedHumidityValue.d.ts +4 -0
- package/lib/interfaces/baseDevices/undefinedHumidityValue.js +7 -0
- package/lib/interfaces/baseDevices/undefinedSoilMoistureValue.d.ts +6 -0
- package/lib/interfaces/baseDevices/undefinedSoilMoistureValue.js +9 -0
- package/lib/interfaces/baseDevices/undefinedTempValue.d.ts +4 -0
- package/lib/interfaces/baseDevices/undefinedTempValue.js +7 -0
- package/lib/interfaces/dachs/KeyListEntity.d.ts +0 -5
- package/lib/interfaces/dachs/KeyListEntityResponse.d.ts +6 -0
- package/lib/interfaces/dachs/KeyListEntityResponse.js +2 -0
- package/lib/interfaces/dachs/index.d.ts +1 -0
- package/lib/interfaces/dachs/index.js +1 -0
- package/lib/interfaces/deviceSettings/iDachsDeviceSettings.d.ts +15 -0
- package/lib/interfaces/iActuatorStateSample.d.ts +13 -0
- package/lib/interfaces/iActuatorStateSample.js +2 -0
- package/lib/interfaces/iBatteryLevelSample.d.ts +13 -0
- package/lib/interfaces/iBatteryLevelSample.js +2 -0
- package/lib/interfaces/iConsumptionWindowSample.d.ts +26 -0
- package/lib/interfaces/iConsumptionWindowSample.js +2 -0
- package/lib/interfaces/iDachsHistoryGateResult.d.ts +29 -0
- package/lib/interfaces/iDachsHistoryGateResult.js +2 -0
- package/lib/interfaces/iEnergyHistoryBasis.d.ts +26 -0
- package/lib/interfaces/iEnergyHistoryBasis.js +2 -0
- package/lib/interfaces/iEnergyHistoryEstimate.d.ts +21 -0
- package/lib/interfaces/iEnergyHistoryEstimate.js +2 -0
- package/lib/interfaces/iEnergyHistoryFeatures.d.ts +21 -0
- package/lib/interfaces/iEnergyHistoryFeatures.js +2 -0
- package/lib/interfaces/iEnergyHistoryModel.d.ts +21 -0
- package/lib/interfaces/iEnergyHistoryModel.js +2 -0
- package/lib/interfaces/iEnergyHistoryOptions.d.ts +29 -0
- package/lib/interfaces/iEnergyHistoryOptions.js +2 -0
- package/lib/interfaces/iEnergyHistoryOutlook.d.ts +41 -0
- package/lib/interfaces/iEnergyHistoryOutlook.js +2 -0
- package/lib/interfaces/iEnergyHistorySample.d.ts +19 -0
- package/lib/interfaces/iEnergyHistorySample.js +2 -0
- package/lib/interfaces/iFossilGeneratorRun.d.ts +22 -0
- package/lib/interfaces/iFossilGeneratorRun.js +2 -0
- package/lib/interfaces/iFossilGeneratorSource.d.ts +21 -0
- package/lib/interfaces/iFossilGeneratorSource.js +2 -0
- package/lib/interfaces/iMorningReserveVerdict.d.ts +38 -0
- package/lib/interfaces/iMorningReserveVerdict.js +2 -0
- package/lib/interfaces/iPersist.d.ts +69 -1
- package/lib/interfaces/iProjectedSocBand.d.ts +7 -0
- package/lib/interfaces/iProjectedSocBand.js +2 -0
- package/lib/interfaces/iSoilMoistureSample.d.ts +13 -0
- package/lib/interfaces/iSoilMoistureSample.js +2 -0
- package/lib/interfaces/iWeatherDaySummary.d.ts +33 -0
- package/lib/interfaces/iWeatherDaySummary.js +2 -0
- package/lib/interfaces/index.d.ts +17 -0
- package/lib/interfaces/index.js +17 -0
- package/lib/services/dbo/actuator-state-row.d.ts +14 -0
- package/lib/services/dbo/actuator-state-row.js +2 -0
- package/lib/services/dbo/battery-level-row.d.ts +16 -0
- package/lib/services/dbo/battery-level-row.js +2 -0
- package/lib/services/dbo/energy-consumption-row.d.ts +16 -0
- package/lib/services/dbo/energy-consumption-row.js +2 -0
- package/lib/services/dbo/postgreSqlPersist.d.ts +52 -1
- package/lib/services/dbo/postgreSqlPersist.js +392 -27
- package/lib/services/dbo/soil-moisture-row.d.ts +14 -0
- package/lib/services/dbo/soil-moisture-row.js +2 -0
- package/lib/services/dbo/weather-day-summary-row.d.ts +20 -0
- package/lib/services/dbo/weather-day-summary-row.js +2 -0
- package/lib/services/energy/energy-history-service.d.ts +168 -0
- package/lib/services/energy/energy-history-service.js +499 -0
- package/lib/services/energy/index.d.ts +1 -0
- package/lib/services/energy/index.js +17 -0
- package/lib/services/energy/plant-energy-dials.d.ts +22 -0
- package/lib/services/energy/plant-energy-dials.js +2 -0
- package/lib/services/https-service.d.ts +48 -2
- package/lib/services/https-service.js +136 -10
- package/lib/services/index.d.ts +1 -0
- package/lib/services/index.js +1 -0
- package/lib/services/time-callback-service.d.ts +12 -0
- package/lib/services/time-callback-service.js +16 -2
- package/lib/services/weather/index.d.ts +1 -0
- package/lib/services/weather/index.js +1 -0
- package/lib/services/weather/open-weather-day-summary.d.ts +25 -0
- package/lib/services/weather/open-weather-day-summary.js +2 -0
- package/lib/services/weather/weather-day-summary-fetcher.d.ts +6 -0
- package/lib/services/weather/weather-day-summary-fetcher.js +2 -0
- package/lib/services/weather/weather-history-backfill.d.ts +94 -0
- package/lib/services/weather/weather-history-backfill.js +247 -0
- package/lib/services/weather/weather-service.js +29 -4
- package/lib/settings-service-instance.js +5 -2
- package/lib/settingsObjects/deviceSettings/dachsSettings.d.ts +6 -0
- package/lib/settingsObjects/deviceSettings/dachsSettings.js +14 -1
- package/lib/settingsObjects/deviceSettings/victronDeviceSettings.d.ts +116 -0
- package/lib/settingsObjects/deviceSettings/victronDeviceSettings.js +150 -5
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/utils/dayMs.d.ts +7 -0
- package/lib/utils/dayMs.js +10 -0
- package/lib/utils/energy-history-dials.d.ts +19 -0
- package/lib/utils/energy-history-dials.js +2 -0
- package/lib/utils/energy-history-utils.d.ts +143 -0
- package/lib/utils/energy-history-utils.js +470 -0
- package/lib/utils/energy-manager-utils.d.ts +123 -1
- package/lib/utils/energy-manager-utils.js +226 -0
- package/lib/utils/index.d.ts +4 -0
- package/lib/utils/index.js +4 -0
- package/lib/utils/model-shadow.d.ts +61 -0
- package/lib/utils/model-shadow.js +83 -0
- package/lib/utils/morning-reserve-dials.d.ts +21 -0
- package/lib/utils/morning-reserve-dials.js +2 -0
- package/lib/utils/morning-verdict.d.ts +5 -0
- package/lib/utils/morning-verdict.js +2 -0
- package/lib/utils/utils.d.ts +0 -1
- package/lib/utils/utils.js +5 -5
- package/package.json +3 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IoBrokerBaseDevice } from '../IoBrokerBaseDevice';
|
|
2
|
-
import { iDisposable, iEnergyManager, iExcessEnergyConsumer } from '../../interfaces';
|
|
2
|
+
import { iDisposable, iEnergyHistoryOutlook, iEnergyManager, iExcessEnergyConsumer, iMorningReserveVerdict } from '../../interfaces';
|
|
3
3
|
import { IoBrokerDeviceInfo } from '../IoBrokerDeviceInfo';
|
|
4
4
|
import { PhaseState } from '../models';
|
|
5
5
|
export declare class JsObjectEnergyManager extends IoBrokerBaseDevice implements iEnergyManager, iDisposable {
|
|
@@ -24,6 +24,21 @@ export declare class JsObjectEnergyManager extends IoBrokerBaseDevice implements
|
|
|
24
24
|
get excessEnergy(): number;
|
|
25
25
|
/** @inheritDoc */
|
|
26
26
|
get acBlocked(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The same shared implementation the other energy manager delegates to - not a stub, and not a copy. This
|
|
29
|
+
* manager measures three phases and carries neither a battery nor the dials that say how a history is read,
|
|
30
|
+
* so the shared code answers nothing for it and reads nothing for it either. That is the honest answer and
|
|
31
|
+
* the one an installation on this manager already got; it is reached by running the real path rather than
|
|
32
|
+
* by declaring it here.
|
|
33
|
+
* @inheritDoc
|
|
34
|
+
*/
|
|
35
|
+
get morningOutlook(): iEnergyHistoryOutlook | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Delegated for the same reason {@link morningOutlook} is - and it answers nothing here for the same reason
|
|
38
|
+
* too: this manager states neither the reserve nor the sun threshold a verdict would be measured against.
|
|
39
|
+
* @inheritDoc
|
|
40
|
+
*/
|
|
41
|
+
get morningReserveVerdict(): iMorningReserveVerdict | undefined;
|
|
27
42
|
private _excessEnergyConsumerConsumption;
|
|
28
43
|
/**
|
|
29
44
|
* Example:
|
|
@@ -62,6 +62,25 @@ class JsObjectEnergyManager extends IoBrokerBaseDevice_1.IoBrokerBaseDevice {
|
|
|
62
62
|
get acBlocked() {
|
|
63
63
|
return this.excessEnergy < 200;
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* The same shared implementation the other energy manager delegates to - not a stub, and not a copy. This
|
|
67
|
+
* manager measures three phases and carries neither a battery nor the dials that say how a history is read,
|
|
68
|
+
* so the shared code answers nothing for it and reads nothing for it either. That is the honest answer and
|
|
69
|
+
* the one an installation on this manager already got; it is reached by running the real path rather than
|
|
70
|
+
* by declaring it here.
|
|
71
|
+
* @inheritDoc
|
|
72
|
+
*/
|
|
73
|
+
get morningOutlook() {
|
|
74
|
+
return utils_1.EnergyManagerUtils.morningOutlook(this);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Delegated for the same reason {@link morningOutlook} is - and it answers nothing here for the same reason
|
|
78
|
+
* too: this manager states neither the reserve nor the sun threshold a verdict would be measured against.
|
|
79
|
+
* @inheritDoc
|
|
80
|
+
*/
|
|
81
|
+
get morningReserveVerdict() {
|
|
82
|
+
return utils_1.EnergyManagerUtils.morningReserveVerdict(this, this.morningOutlook);
|
|
83
|
+
}
|
|
65
84
|
/**
|
|
66
85
|
* Example:
|
|
67
86
|
* ________________________________________
|
|
@@ -137,6 +156,10 @@ class JsObjectEnergyManager extends IoBrokerBaseDevice_1.IoBrokerBaseDevice {
|
|
|
137
156
|
}
|
|
138
157
|
}
|
|
139
158
|
calculateExcessEnergy() {
|
|
159
|
+
// The same call the other manager's loop makes, so whether anything is read is decided in one place
|
|
160
|
+
// rather than by which manager happens to ask. This one states no dials, so nothing is read and no
|
|
161
|
+
// request quota is spent.
|
|
162
|
+
utils_1.EnergyManagerUtils.refreshEnergyHistory(this);
|
|
140
163
|
const phaseProduction = this._currentProduction / 3.0;
|
|
141
164
|
this._phaseAState = new models_2.PhaseState(this._powerValuePhaseA, phaseProduction);
|
|
142
165
|
this._phaseBState = new models_2.PhaseState(this._powerValuePhaseB, phaseProduction);
|
|
@@ -20,4 +20,5 @@ __exportStar(require("./handleSensor"), exports);
|
|
|
20
20
|
__exportStar(require("./humiditySensor"), exports);
|
|
21
21
|
__exportStar(require("./lampUtils"), exports);
|
|
22
22
|
__exportStar(require("./shutterUtils"), exports);
|
|
23
|
+
__exportStar(require("./soilSensor"), exports);
|
|
23
24
|
__exportStar(require("./temperatureSensor"), exports);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { iSoilCollector, iSoilSensor } from '../../interfaces';
|
|
2
|
+
import { SoilSensorChangeAction } from '../../action';
|
|
3
|
+
export declare class SoilSensor implements iSoilSensor {
|
|
4
|
+
private readonly _device;
|
|
5
|
+
/** @inheritDoc */
|
|
6
|
+
readonly jsonOmitKeys: string[];
|
|
7
|
+
private _soilMoistureCallbacks;
|
|
8
|
+
private _soilMoisture;
|
|
9
|
+
private readonly _persistSoilSensorInterval;
|
|
10
|
+
constructor(_device: iSoilCollector);
|
|
11
|
+
/** @inheritDoc */
|
|
12
|
+
get soilMoisture(): number;
|
|
13
|
+
/** @inheritDoc */
|
|
14
|
+
set soilMoisture(val: number);
|
|
15
|
+
/** @inheritDoc */
|
|
16
|
+
persist(): void;
|
|
17
|
+
/** @inheritDoc */
|
|
18
|
+
addSoilMoistureCallback(pCallback: (action: SoilSensorChangeAction) => void): void;
|
|
19
|
+
/** @inheritDoc */
|
|
20
|
+
dispose(): void;
|
|
21
|
+
/** @inheritDoc */
|
|
22
|
+
toJSON(): Partial<SoilSensor>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SoilSensor = void 0;
|
|
4
|
+
const interfaces_1 = require("../../interfaces");
|
|
5
|
+
const action_1 = require("../../action");
|
|
6
|
+
const utils_1 = require("../../utils");
|
|
7
|
+
const services_1 = require("../../services");
|
|
8
|
+
class SoilSensor {
|
|
9
|
+
constructor(_device) {
|
|
10
|
+
this._device = _device;
|
|
11
|
+
/** @inheritDoc */
|
|
12
|
+
this.jsonOmitKeys = ['_device'];
|
|
13
|
+
this._soilMoistureCallbacks = [];
|
|
14
|
+
this._soilMoisture = interfaces_1.UNDEFINED_SOIL_MOISTURE_VALUE;
|
|
15
|
+
this._persistSoilSensorInterval = utils_1.Utils.guardedInterval(() => {
|
|
16
|
+
this.persist();
|
|
17
|
+
}, 5 * 60 * 1000, this, false);
|
|
18
|
+
}
|
|
19
|
+
/** @inheritDoc */
|
|
20
|
+
get soilMoisture() {
|
|
21
|
+
return this._soilMoisture;
|
|
22
|
+
}
|
|
23
|
+
/** @inheritDoc */
|
|
24
|
+
set soilMoisture(val) {
|
|
25
|
+
this._soilMoisture = val;
|
|
26
|
+
for (const cb of this._soilMoistureCallbacks) {
|
|
27
|
+
cb(new action_1.SoilSensorChangeAction(this._device, val));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** @inheritDoc */
|
|
31
|
+
persist() {
|
|
32
|
+
var _a;
|
|
33
|
+
if (this._soilMoisture === interfaces_1.UNDEFINED_SOIL_MOISTURE_VALUE) {
|
|
34
|
+
// Nothing was ever reported --> persisting would only write a row of the sentinel, which reads like a
|
|
35
|
+
// measured -1 % in every later query.
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
(_a = services_1.Persistence.dbo) === null || _a === void 0 ? void 0 : _a.persistSoilSensor(this._device);
|
|
39
|
+
}
|
|
40
|
+
/** @inheritDoc */
|
|
41
|
+
addSoilMoistureCallback(pCallback) {
|
|
42
|
+
this._soilMoistureCallbacks.push(pCallback);
|
|
43
|
+
if (this._soilMoisture !== interfaces_1.UNDEFINED_SOIL_MOISTURE_VALUE) {
|
|
44
|
+
pCallback(new action_1.SoilSensorChangeAction(this._device, this._soilMoisture));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** @inheritDoc */
|
|
48
|
+
dispose() {
|
|
49
|
+
if (this._persistSoilSensorInterval) {
|
|
50
|
+
clearInterval(this._persistSoilSensorInterval);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** @inheritDoc */
|
|
54
|
+
toJSON() {
|
|
55
|
+
return utils_1.Utils.jsonFilter(this, this.jsonOmitKeys);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.SoilSensor = SoilSensor;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { iBatteryDevice, iEnergyManager, iExcessEnergyConsumer, iJsonOmitKeys } from '../../interfaces';
|
|
1
|
+
import { iBatteryDevice, iEnergyHistoryOutlook, iEnergyManager, iExcessEnergyConsumer, iJsonOmitKeys, iMorningReserveVerdict } from '../../interfaces';
|
|
2
2
|
import { VictronDeviceSettings } from '../../settingsObjects';
|
|
3
3
|
import { Battery } from '../sharedFunctions';
|
|
4
4
|
import { VictronDeviceData, VictronMqttConnectionOptions, VictronMqttConsumer } from 'victron-mqtt-consumer';
|
|
5
5
|
import { BaseDevice } from '../BaseDevice';
|
|
6
6
|
export declare class VictronDevice extends BaseDevice implements iEnergyManager, iBatteryDevice, iJsonOmitKeys {
|
|
7
|
+
/**
|
|
8
|
+
* The shortest horizon the battery reservation is spread over, in hours. Not a setting: it is a bound on
|
|
9
|
+
* the arithmetic rather than a dial of the plant - see {@link VictronDevice.reserveHorizonHours}.
|
|
10
|
+
*/
|
|
11
|
+
private static readonly minimumReserveHorizonHours;
|
|
7
12
|
/** @inheritDoc */
|
|
8
13
|
readonly settings: VictronDeviceSettings;
|
|
9
14
|
/** @inheritDoc */
|
|
@@ -17,11 +22,28 @@ export declare class VictronDevice extends BaseDevice implements iEnergyManager,
|
|
|
17
22
|
private _lastPersistenceCalculation;
|
|
18
23
|
private _nextPersistEntry;
|
|
19
24
|
private _excessEnergy;
|
|
25
|
+
/** The last reported release state, so the five second loop writes a line on change, not on every pass. */
|
|
26
|
+
private _lastReleaseLine;
|
|
20
27
|
constructor(opts: VictronMqttConnectionOptions);
|
|
21
28
|
/** @inheritDoc */
|
|
22
29
|
get acBlocked(): boolean;
|
|
23
30
|
/** @inheritDoc */
|
|
24
31
|
get batteryLevel(): number;
|
|
32
|
+
/**
|
|
33
|
+
* Delegated rather than written here, exactly the way this device delegates its consumer switching to
|
|
34
|
+
* {@link EnergyManagerUtils.turnOnAdditionalConsumer}: the answer is about the **plant**, and every energy
|
|
35
|
+
* manager owes the same one - so it is written once and no manager is left with a copy or a stub. What this
|
|
36
|
+
* device keeps for itself is the policy: the rungs, the reservation and the ac block.
|
|
37
|
+
* @inheritDoc
|
|
38
|
+
*/
|
|
39
|
+
get morningOutlook(): iEnergyHistoryOutlook | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Delegated for the same reason {@link morningOutlook} is: the judgement is about the plant's battery and
|
|
42
|
+
* every manager owes the same one. What this device keeps for itself is what it *does* with the verdict -
|
|
43
|
+
* the reservation and the ac block below.
|
|
44
|
+
* @inheritDoc
|
|
45
|
+
*/
|
|
46
|
+
get morningReserveVerdict(): iMorningReserveVerdict | undefined;
|
|
25
47
|
get victronConsumer(): VictronMqttConsumer;
|
|
26
48
|
get data(): VictronDeviceData;
|
|
27
49
|
get excessEnergy(): number;
|
|
@@ -33,6 +55,7 @@ export declare class VictronDevice extends BaseDevice implements iEnergyManager,
|
|
|
33
55
|
addExcessConsumer(device: iExcessEnergyConsumer): void;
|
|
34
56
|
/** @inheritDoc */
|
|
35
57
|
dispose(): void;
|
|
58
|
+
/** @inheritDoc */
|
|
36
59
|
getReport(): string;
|
|
37
60
|
recalculatePowerSharing(): void;
|
|
38
61
|
toJSON(): Partial<VictronDevice>;
|
|
@@ -42,6 +65,65 @@ export declare class VictronDevice extends BaseDevice implements iEnergyManager,
|
|
|
42
65
|
*/
|
|
43
66
|
setGridSetPoint(setPoint: number): void;
|
|
44
67
|
private calculateExcessEnergy;
|
|
68
|
+
/**
|
|
69
|
+
* Rung 1, the only rung of the recorded history that decides: if the state of charge carries past the
|
|
70
|
+
* coming morning low even when no further yield arrives, nothing has to be held back and no consumer has to
|
|
71
|
+
* be kept off.
|
|
72
|
+
*
|
|
73
|
+
* This manager's own policy and rightly here rather than in the shared utils: what a plant does with the
|
|
74
|
+
* outlook is the manager's judgement, and the reservation and ac block it feeds are this device's.
|
|
75
|
+
*
|
|
76
|
+
* Arithmetic over the plant's own measured consumption - no fit, no weights, no window length. That is what
|
|
77
|
+
* separates it from the rung below, which measures against the lower edge of the fitted band and therefore
|
|
78
|
+
* only records (see {@link EnergyManagerUtils.observeModelShadow}).
|
|
79
|
+
* @param outlook - What the plant said, or undefined while it cannot say anything - which includes the
|
|
80
|
+
* absent charge level, so the guard against it stays in the shared utils alone.
|
|
81
|
+
* @returns The release, or undefined while the measured consumption cannot carry it.
|
|
82
|
+
*/
|
|
83
|
+
private morningRelease;
|
|
84
|
+
/**
|
|
85
|
+
* How much of the production is held back for the battery.
|
|
86
|
+
*
|
|
87
|
+
* With the release nothing is held back: the coming morning clears the reserve on measured consumption
|
|
88
|
+
* alone. Without it the calculation is the one that was here before - it aims at a full battery by sunset,
|
|
89
|
+
* which over-reserves, and that is what an installation without a usable recorded history keeps.
|
|
90
|
+
* @param released - Whether rung 1 carried the coming morning.
|
|
91
|
+
* @param hoursTilSunset - The horizon the shortfall is spread over.
|
|
92
|
+
* @returns The wattage to hold back.
|
|
93
|
+
*/
|
|
94
|
+
private neededBatteryWattage;
|
|
95
|
+
/**
|
|
96
|
+
* The horizon the shortfall is actually spread over: the remaining sun hours, but never less than
|
|
97
|
+
* {@link VictronDevice.minimumReserveHorizonHours}.
|
|
98
|
+
*
|
|
99
|
+
* The raw horizon is a difference against the next sunset and runs to zero, while the part of day this
|
|
100
|
+
* calculation is entered under is derived separately from today's sunset plus its own offsets - so the two
|
|
101
|
+
* do not turn at the same instant. In the gap the divisor is first tiny and then negative: a shortfall of a
|
|
102
|
+
* few percent becomes a rate in the megawatt range, at exactly zero an `Infinity` that leaves the process
|
|
103
|
+
* through `toJSON`, and past the turn a *negative* reservation that is added to the excess and offers
|
|
104
|
+
* energy the plant does not have. Every five seconds, and since the horizon is counted in hours rather than
|
|
105
|
+
* minutes, sixty times as large as when this was harmless.
|
|
106
|
+
*
|
|
107
|
+
* The bound is a rate bound, not a schedule: below half an hour of daylight there is nothing left to charge
|
|
108
|
+
* in, so the quotient stops describing a charging rate and only its magnitude still moves. Half an hour
|
|
109
|
+
* caps the reservation at twice the battery capacity per hour - still above anything the plant can take in,
|
|
110
|
+
* therefore never loosening a reservation that was meaningful, while keeping the value finite and signed
|
|
111
|
+
* the way the rest of the calculation assumes.
|
|
112
|
+
* @param hoursTilSunset - The raw remaining sun hours, which may be zero or negative.
|
|
113
|
+
* @returns The horizon to divide by, at least the minimum.
|
|
114
|
+
*/
|
|
115
|
+
private reserveHorizonHours;
|
|
116
|
+
/**
|
|
117
|
+
* Reports the release whenever it changes, and never otherwise: this runs every five seconds, and a line
|
|
118
|
+
* per pass would bury the change nobody must miss. The very first pass is remembered but not reported while
|
|
119
|
+
* there is no release, so an installation whose recorded history holds nothing stays silent instead of
|
|
120
|
+
* announcing its unchanged behaviour once per start.
|
|
121
|
+
*
|
|
122
|
+
* Named after the reserve rather than after the reservation, because the same release also answers the ac
|
|
123
|
+
* block - and it does so around the clock, while the reservation only applies in daylight.
|
|
124
|
+
* @param release - The release of this pass, or undefined while the measured consumption cannot carry one.
|
|
125
|
+
*/
|
|
126
|
+
private logMorningRelease;
|
|
45
127
|
private turnOnAdditionalConsumer;
|
|
46
128
|
private turnOffAdditionalConsumer;
|
|
47
129
|
private persist;
|
|
@@ -50,6 +50,16 @@ class VictronDevice extends BaseDevice_1.BaseDevice {
|
|
|
50
50
|
if (!this.settings.hasBattery) {
|
|
51
51
|
return false;
|
|
52
52
|
}
|
|
53
|
+
if (this.morningRelease(this.morningOutlook) !== undefined) {
|
|
54
|
+
// Where the plant's measured consumption alone shows the coming morning clears the reserve, that
|
|
55
|
+
// statement decides and the clock does not. The ladder below is a stand-in for the same question, and
|
|
56
|
+
// its sunny morning branch cannot answer the case it was built for: it reads the day's mean cloud
|
|
57
|
+
// cover, which a day that is dull in the morning and clears up at noon never falls below.
|
|
58
|
+
//
|
|
59
|
+
// Only the release direction. Blocking on the model would mean acting on the fitted band, which is
|
|
60
|
+
// exactly what the shadow exists to defer.
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
53
63
|
const hours = new Date().getHours();
|
|
54
64
|
if (hours > 18) {
|
|
55
65
|
return this.batteryLevel < this.settings.minimumNightTimeAcBatteryLevel;
|
|
@@ -81,6 +91,25 @@ class VictronDevice extends BaseDevice_1.BaseDevice {
|
|
|
81
91
|
}
|
|
82
92
|
return level;
|
|
83
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Delegated rather than written here, exactly the way this device delegates its consumer switching to
|
|
96
|
+
* {@link EnergyManagerUtils.turnOnAdditionalConsumer}: the answer is about the **plant**, and every energy
|
|
97
|
+
* manager owes the same one - so it is written once and no manager is left with a copy or a stub. What this
|
|
98
|
+
* device keeps for itself is the policy: the rungs, the reservation and the ac block.
|
|
99
|
+
* @inheritDoc
|
|
100
|
+
*/
|
|
101
|
+
get morningOutlook() {
|
|
102
|
+
return utils_1.EnergyManagerUtils.morningOutlook(this);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Delegated for the same reason {@link morningOutlook} is: the judgement is about the plant's battery and
|
|
106
|
+
* every manager owes the same one. What this device keeps for itself is what it *does* with the verdict -
|
|
107
|
+
* the reservation and the ac block below.
|
|
108
|
+
* @inheritDoc
|
|
109
|
+
*/
|
|
110
|
+
get morningReserveVerdict() {
|
|
111
|
+
return utils_1.EnergyManagerUtils.morningReserveVerdict(this, this.morningOutlook);
|
|
112
|
+
}
|
|
84
113
|
get victronConsumer() {
|
|
85
114
|
return this._victronConsumer;
|
|
86
115
|
}
|
|
@@ -124,8 +153,16 @@ class VictronDevice extends BaseDevice_1.BaseDevice {
|
|
|
124
153
|
this._iCalculationInterval = null;
|
|
125
154
|
}
|
|
126
155
|
}
|
|
156
|
+
/** @inheritDoc */
|
|
127
157
|
getReport() {
|
|
128
|
-
|
|
158
|
+
var _a;
|
|
159
|
+
const response = [];
|
|
160
|
+
response.push(`Production: ${(_a = this.data.pvInverter.power) !== null && _a !== void 0 ? _a : 0}W`);
|
|
161
|
+
response.push(`Drawing Wattage: ${this.drawingWattage}W`);
|
|
162
|
+
response.push(`Injecting Wattage: ${this.injectingWattage}W`);
|
|
163
|
+
response.push(`Self Consuming Wattage: ${this.selfConsumingWattage}W`);
|
|
164
|
+
response.push(`Battery Level: ${this.batteryLevel}%`);
|
|
165
|
+
return response.join('\n');
|
|
129
166
|
}
|
|
130
167
|
recalculatePowerSharing() {
|
|
131
168
|
this.calculateExcessEnergy();
|
|
@@ -167,6 +204,19 @@ class VictronDevice extends BaseDevice_1.BaseDevice {
|
|
|
167
204
|
this.log(enums_1.LogLevel.Debug, 'No data available from Victron device.');
|
|
168
205
|
return;
|
|
169
206
|
}
|
|
207
|
+
// The manager's loop is what drives the plant's one reading, for every consumer of it. Asked, not
|
|
208
|
+
// scheduled: what it costs is decided by the data situation rather than by a setting, and each of the
|
|
209
|
+
// reads behind this throttles itself, so asking on every pass of the five second loop costs the same
|
|
210
|
+
// number of queries as asking once an hour.
|
|
211
|
+
utils_1.EnergyManagerUtils.refreshEnergyHistory(this);
|
|
212
|
+
// Read once and handed on, rather than each of the three asking again: the projection is arithmetic over
|
|
213
|
+
// one read, and three passes over it would still have to agree with each other.
|
|
214
|
+
const outlook = this.morningOutlook;
|
|
215
|
+
const release = this.morningRelease(outlook);
|
|
216
|
+
this.logMorningRelease(release);
|
|
217
|
+
// Fed from here and from nowhere else. `acBlocked` is a getter anyone may read at any rate, and a tally
|
|
218
|
+
// that counts reads rather than evaluations measures the callers instead of the model.
|
|
219
|
+
utils_1.EnergyManagerUtils.observeModelShadow(this, outlook, release !== undefined);
|
|
170
220
|
// Step 1: Calculate battery need
|
|
171
221
|
const hoursTilSunset = services_1.TimeCallbackService.hoursTilSunset();
|
|
172
222
|
let neededBatteryWattage = 0;
|
|
@@ -176,7 +226,7 @@ class VictronDevice extends BaseDevice_1.BaseDevice {
|
|
|
176
226
|
this.log(enums_1.LogLevel.Debug, 'No battery data available from Victron device.');
|
|
177
227
|
return;
|
|
178
228
|
}
|
|
179
|
-
neededBatteryWattage =
|
|
229
|
+
neededBatteryWattage = this.neededBatteryWattage(release !== undefined, hoursTilSunset);
|
|
180
230
|
// Step 2: Calculate expected solar output
|
|
181
231
|
const solarOutput = (_a = this.data.pvInverter.power) !== null && _a !== void 0 ? _a : 0;
|
|
182
232
|
// Step 3: Calculate expected base consumption
|
|
@@ -205,6 +255,100 @@ class VictronDevice extends BaseDevice_1.BaseDevice {
|
|
|
205
255
|
}
|
|
206
256
|
this.calculatePersistenceValues();
|
|
207
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* Rung 1, the only rung of the recorded history that decides: if the state of charge carries past the
|
|
260
|
+
* coming morning low even when no further yield arrives, nothing has to be held back and no consumer has to
|
|
261
|
+
* be kept off.
|
|
262
|
+
*
|
|
263
|
+
* This manager's own policy and rightly here rather than in the shared utils: what a plant does with the
|
|
264
|
+
* outlook is the manager's judgement, and the reservation and ac block it feeds are this device's.
|
|
265
|
+
*
|
|
266
|
+
* Arithmetic over the plant's own measured consumption - no fit, no weights, no window length. That is what
|
|
267
|
+
* separates it from the rung below, which measures against the lower edge of the fitted band and therefore
|
|
268
|
+
* only records (see {@link EnergyManagerUtils.observeModelShadow}).
|
|
269
|
+
* @param outlook - What the plant said, or undefined while it cannot say anything - which includes the
|
|
270
|
+
* absent charge level, so the guard against it stays in the shared utils alone.
|
|
271
|
+
* @returns The release, or undefined while the measured consumption cannot carry it.
|
|
272
|
+
*/
|
|
273
|
+
morningRelease(outlook) {
|
|
274
|
+
if (outlook === undefined) {
|
|
275
|
+
// The fallback holds back more, not less.
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
const reserve = this.settings.minimumMorningSocReserve;
|
|
279
|
+
const worstCaseLowSoc = outlook.worstCaseLowSoc;
|
|
280
|
+
if (worstCaseLowSoc === undefined || worstCaseLowSoc < reserve) {
|
|
281
|
+
return undefined;
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
reason: `worst case low ${utils_1.Utils.round(worstCaseLowSoc, 2)}% holds the reserve ${reserve}% ` +
|
|
285
|
+
'without any further yield',
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* How much of the production is held back for the battery.
|
|
290
|
+
*
|
|
291
|
+
* With the release nothing is held back: the coming morning clears the reserve on measured consumption
|
|
292
|
+
* alone. Without it the calculation is the one that was here before - it aims at a full battery by sunset,
|
|
293
|
+
* which over-reserves, and that is what an installation without a usable recorded history keeps.
|
|
294
|
+
* @param released - Whether rung 1 carried the coming morning.
|
|
295
|
+
* @param hoursTilSunset - The horizon the shortfall is spread over.
|
|
296
|
+
* @returns The wattage to hold back.
|
|
297
|
+
*/
|
|
298
|
+
neededBatteryWattage(released, hoursTilSunset) {
|
|
299
|
+
if (released) {
|
|
300
|
+
return 0;
|
|
301
|
+
}
|
|
302
|
+
const missingShare = 1 - this.batteryLevel / 100.0;
|
|
303
|
+
return (missingShare * this.settings.batteryCapacityWattage) / this.reserveHorizonHours(hoursTilSunset);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* The horizon the shortfall is actually spread over: the remaining sun hours, but never less than
|
|
307
|
+
* {@link VictronDevice.minimumReserveHorizonHours}.
|
|
308
|
+
*
|
|
309
|
+
* The raw horizon is a difference against the next sunset and runs to zero, while the part of day this
|
|
310
|
+
* calculation is entered under is derived separately from today's sunset plus its own offsets - so the two
|
|
311
|
+
* do not turn at the same instant. In the gap the divisor is first tiny and then negative: a shortfall of a
|
|
312
|
+
* few percent becomes a rate in the megawatt range, at exactly zero an `Infinity` that leaves the process
|
|
313
|
+
* through `toJSON`, and past the turn a *negative* reservation that is added to the excess and offers
|
|
314
|
+
* energy the plant does not have. Every five seconds, and since the horizon is counted in hours rather than
|
|
315
|
+
* minutes, sixty times as large as when this was harmless.
|
|
316
|
+
*
|
|
317
|
+
* The bound is a rate bound, not a schedule: below half an hour of daylight there is nothing left to charge
|
|
318
|
+
* in, so the quotient stops describing a charging rate and only its magnitude still moves. Half an hour
|
|
319
|
+
* caps the reservation at twice the battery capacity per hour - still above anything the plant can take in,
|
|
320
|
+
* therefore never loosening a reservation that was meaningful, while keeping the value finite and signed
|
|
321
|
+
* the way the rest of the calculation assumes.
|
|
322
|
+
* @param hoursTilSunset - The raw remaining sun hours, which may be zero or negative.
|
|
323
|
+
* @returns The horizon to divide by, at least the minimum.
|
|
324
|
+
*/
|
|
325
|
+
reserveHorizonHours(hoursTilSunset) {
|
|
326
|
+
return Math.max(hoursTilSunset, VictronDevice.minimumReserveHorizonHours);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Reports the release whenever it changes, and never otherwise: this runs every five seconds, and a line
|
|
330
|
+
* per pass would bury the change nobody must miss. The very first pass is remembered but not reported while
|
|
331
|
+
* there is no release, so an installation whose recorded history holds nothing stays silent instead of
|
|
332
|
+
* announcing its unchanged behaviour once per start.
|
|
333
|
+
*
|
|
334
|
+
* Named after the reserve rather than after the reservation, because the same release also answers the ac
|
|
335
|
+
* block - and it does so around the clock, while the reservation only applies in daylight.
|
|
336
|
+
* @param release - The release of this pass, or undefined while the measured consumption cannot carry one.
|
|
337
|
+
*/
|
|
338
|
+
logMorningRelease(release) {
|
|
339
|
+
const line = release === undefined
|
|
340
|
+
? 'no model free release, aiming at a full battery by sunset'
|
|
341
|
+
: `released: ${release.reason}`;
|
|
342
|
+
if (line === this._lastReleaseLine) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
const first = this._lastReleaseLine === undefined;
|
|
346
|
+
this._lastReleaseLine = line;
|
|
347
|
+
if (first && release === undefined) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
this.log(enums_1.LogLevel.Info, `Morning reserve decision: ${line}`);
|
|
351
|
+
}
|
|
208
352
|
turnOnAdditionalConsumer() {
|
|
209
353
|
const result = utils_1.EnergyManagerUtils.turnOnAdditionalConsumer(this._excessEnergyConsumer, this._lastDeviceChange);
|
|
210
354
|
if (result == undefined) {
|
|
@@ -249,3 +393,8 @@ class VictronDevice extends BaseDevice_1.BaseDevice {
|
|
|
249
393
|
}
|
|
250
394
|
}
|
|
251
395
|
exports.VictronDevice = VictronDevice;
|
|
396
|
+
/**
|
|
397
|
+
* The shortest horizon the battery reservation is spread over, in hours. Not a setting: it is a bound on
|
|
398
|
+
* the arithmetic rather than a dial of the plant - see {@link VictronDevice.reserveHorizonHours}.
|
|
399
|
+
*/
|
|
400
|
+
VictronDevice.minimumReserveHorizonHours = 0.5;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one statement the plant's recorded history is allowed to act on in the victron manager: that the coming
|
|
3
|
+
* morning low clears the reserve on measured consumption alone, with no further yield assumed and no model
|
|
4
|
+
* involved.
|
|
5
|
+
*
|
|
6
|
+
* There is no counterpart for "the morning falls short". Saying so needs the fitted model, and the model runs
|
|
7
|
+
* in the shadow; the absent value therefore means the previous calculation applies, which needs nothing from
|
|
8
|
+
* the history.
|
|
9
|
+
*
|
|
10
|
+
* Not part of the published surface: it is how this manager carries its own decision from one private method
|
|
11
|
+
* to the next, not something a consumer of the library reads.
|
|
12
|
+
*/
|
|
13
|
+
export interface iVictronMorningRelease {
|
|
14
|
+
/** What an operator reads the release by. */
|
|
15
|
+
reason: string;
|
|
16
|
+
}
|
|
@@ -6,6 +6,7 @@ export * from './zigbeeLedRGBCCT';
|
|
|
6
6
|
export * from './zigbeeMagnetContact';
|
|
7
7
|
export * from './zigbeeMotionSensor';
|
|
8
8
|
export * from './zigbeeShutter';
|
|
9
|
+
export * from './zigbeeSoilSensor';
|
|
9
10
|
export * from './zigbeeSwitch';
|
|
10
11
|
export { ZigbeeLamp } from './zigbeeLamp';
|
|
11
12
|
export { ZigbeeWindowHandle } from './zigbeeWindowHandle';
|
|
@@ -23,6 +23,7 @@ __exportStar(require("./zigbeeLedRGBCCT"), exports);
|
|
|
23
23
|
__exportStar(require("./zigbeeMagnetContact"), exports);
|
|
24
24
|
__exportStar(require("./zigbeeMotionSensor"), exports);
|
|
25
25
|
__exportStar(require("./zigbeeShutter"), exports);
|
|
26
|
+
__exportStar(require("./zigbeeSoilSensor"), exports);
|
|
26
27
|
__exportStar(require("./zigbeeSwitch"), exports);
|
|
27
28
|
var zigbeeLamp_1 = require("./zigbeeLamp");
|
|
28
29
|
Object.defineProperty(exports, "ZigbeeLamp", { enumerable: true, get: function () { return zigbeeLamp_1.ZigbeeLamp; } });
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { iBatteryDevice, iSoilCollector, iSoilSensor } from '../../../interfaces';
|
|
2
|
+
import { BatteryLevelChangeAction, SoilSensorChangeAction } from '../../../action';
|
|
3
|
+
import { ZigbeeDevice } from './zigbeeDevice';
|
|
4
|
+
import { Battery } from '../../sharedFunctions';
|
|
5
|
+
import { IoBrokerDeviceInfo } from '../../IoBrokerDeviceInfo';
|
|
6
|
+
import { DeviceType } from '../../../enums';
|
|
7
|
+
/**
|
|
8
|
+
* The common part of every zigbee device measuring the moisture of the soil it sits in.
|
|
9
|
+
*
|
|
10
|
+
* Carries the smallest honest contract: soil moisture and battery, the two states every such sensor reports.
|
|
11
|
+
* Ambient temperature and humidity are deliberately NOT here - a sensor that only reads the soil would then
|
|
12
|
+
* claim capabilities it does not have. A device that measures them adds those axes itself, see
|
|
13
|
+
* {@link ZigbeeCooloSoilSensor}.
|
|
14
|
+
*/
|
|
15
|
+
export declare class ZigbeeSoilSensor extends ZigbeeDevice implements iSoilCollector, iBatteryDevice {
|
|
16
|
+
/** @inheritDoc */
|
|
17
|
+
soilSensor: iSoilSensor;
|
|
18
|
+
/** @inheritDoc */
|
|
19
|
+
battery: Battery;
|
|
20
|
+
constructor(pInfo: IoBrokerDeviceInfo, pType: DeviceType);
|
|
21
|
+
/** @inheritDoc */
|
|
22
|
+
get batteryLevel(): number;
|
|
23
|
+
/** @inheritDoc */
|
|
24
|
+
get soilMoisture(): number;
|
|
25
|
+
/** @inheritDoc */
|
|
26
|
+
addBatteryLevelCallback(pCallback: (action: BatteryLevelChangeAction) => void): void;
|
|
27
|
+
/** @inheritDoc */
|
|
28
|
+
addSoilMoistureCallback(pCallback: (action: SoilSensorChangeAction) => void): void;
|
|
29
|
+
/** @inheritDoc */
|
|
30
|
+
update(idSplit: string[], state: ioBroker.State, initial?: boolean): void;
|
|
31
|
+
/** @inheritDoc */
|
|
32
|
+
dispose(): void;
|
|
33
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ZigbeeSoilSensor = void 0;
|
|
4
|
+
const zigbeeDevice_1 = require("./zigbeeDevice");
|
|
5
|
+
const sharedFunctions_1 = require("../../sharedFunctions");
|
|
6
|
+
const enums_1 = require("../../../enums");
|
|
7
|
+
/**
|
|
8
|
+
* The common part of every zigbee device measuring the moisture of the soil it sits in.
|
|
9
|
+
*
|
|
10
|
+
* Carries the smallest honest contract: soil moisture and battery, the two states every such sensor reports.
|
|
11
|
+
* Ambient temperature and humidity are deliberately NOT here - a sensor that only reads the soil would then
|
|
12
|
+
* claim capabilities it does not have. A device that measures them adds those axes itself, see
|
|
13
|
+
* {@link ZigbeeCooloSoilSensor}.
|
|
14
|
+
*/
|
|
15
|
+
class ZigbeeSoilSensor extends zigbeeDevice_1.ZigbeeDevice {
|
|
16
|
+
constructor(pInfo, pType) {
|
|
17
|
+
super(pInfo, pType);
|
|
18
|
+
/** @inheritDoc */
|
|
19
|
+
this.soilSensor = new sharedFunctions_1.SoilSensor(this);
|
|
20
|
+
/** @inheritDoc */
|
|
21
|
+
this.battery = new sharedFunctions_1.Battery(this);
|
|
22
|
+
this.deviceCapabilities.push(enums_1.DeviceCapability.soilSensor);
|
|
23
|
+
this.deviceCapabilities.push(enums_1.DeviceCapability.batteryDriven);
|
|
24
|
+
}
|
|
25
|
+
/** @inheritDoc */
|
|
26
|
+
get batteryLevel() {
|
|
27
|
+
return this.battery.level;
|
|
28
|
+
}
|
|
29
|
+
/** @inheritDoc */
|
|
30
|
+
get soilMoisture() {
|
|
31
|
+
return this.soilSensor.soilMoisture;
|
|
32
|
+
}
|
|
33
|
+
/** @inheritDoc */
|
|
34
|
+
addBatteryLevelCallback(pCallback) {
|
|
35
|
+
this.battery.addBatteryLevelCallback(pCallback);
|
|
36
|
+
}
|
|
37
|
+
/** @inheritDoc */
|
|
38
|
+
addSoilMoistureCallback(pCallback) {
|
|
39
|
+
this.soilSensor.addSoilMoistureCallback(pCallback);
|
|
40
|
+
}
|
|
41
|
+
/** @inheritDoc */
|
|
42
|
+
update(idSplit, state, initial = false) {
|
|
43
|
+
super.update(idSplit, state, initial, true);
|
|
44
|
+
switch (idSplit[3]) {
|
|
45
|
+
case 'battery':
|
|
46
|
+
this.battery.level = state.val;
|
|
47
|
+
if (this.batteryLevel < 20) {
|
|
48
|
+
this.log(enums_1.LogLevel.Warn, 'Das Zigbee Gerät hat unter 20% Batterie.');
|
|
49
|
+
}
|
|
50
|
+
break;
|
|
51
|
+
case 'soil_moisture':
|
|
52
|
+
this.soilSensor.soilMoisture = state.val;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** @inheritDoc */
|
|
57
|
+
dispose() {
|
|
58
|
+
this.soilSensor.dispose();
|
|
59
|
+
super.dispose();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.ZigbeeSoilSensor = ZigbeeSoilSensor;
|
|
@@ -6,6 +6,7 @@ export * from './zigbeeAqaraPresence';
|
|
|
6
6
|
export * from './zigbeeAquaraVibra';
|
|
7
7
|
export * from './zigbeeAquaraWater';
|
|
8
8
|
export * from './zigbeeBlitzShp';
|
|
9
|
+
export * from './zigbeeCooloSoilSensor';
|
|
9
10
|
export * from './zigbeeEuroHeater';
|
|
10
11
|
export * from './zigbeeHeimanSmoke';
|
|
11
12
|
export * from './zigbeeIkeaSteckdose';
|
|
@@ -23,6 +23,7 @@ __exportStar(require("./zigbeeAqaraPresence"), exports);
|
|
|
23
23
|
__exportStar(require("./zigbeeAquaraVibra"), exports);
|
|
24
24
|
__exportStar(require("./zigbeeAquaraWater"), exports);
|
|
25
25
|
__exportStar(require("./zigbeeBlitzShp"), exports);
|
|
26
|
+
__exportStar(require("./zigbeeCooloSoilSensor"), exports);
|
|
26
27
|
__exportStar(require("./zigbeeEuroHeater"), exports);
|
|
27
28
|
__exportStar(require("./zigbeeHeimanSmoke"), exports);
|
|
28
29
|
__exportStar(require("./zigbeeIkeaSteckdose"), exports);
|