hoffmation-base 3.6.0 → 3.7.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/airQualitySensorChangeAction.d.ts +16 -0
- package/lib/action/airQualitySensorChangeAction.js +15 -0
- package/lib/action/index.d.ts +1 -0
- package/lib/action/index.js +3 -1
- package/lib/devices/sharedFunctions/airQualitySensor.d.ts +27 -0
- package/lib/devices/sharedFunctions/airQualitySensor.js +87 -0
- package/lib/devices/sharedFunctions/index.d.ts +1 -0
- package/lib/devices/sharedFunctions/index.js +1 -0
- package/lib/devices/unifi/index.d.ts +1 -0
- package/lib/devices/unifi/index.js +1 -0
- package/lib/devices/unifi/own-unifi-air-quality-sensor.d.ts +81 -0
- package/lib/devices/unifi/own-unifi-air-quality-sensor.js +164 -0
- package/lib/devices/unifi/own-unifi-camera.d.ts +6 -5
- package/lib/devices/unifi/own-unifi-camera.js +14 -24
- package/lib/devices/unifi/protect-module.d.ts +11 -0
- package/lib/devices/unifi/protect-module.js +16 -0
- package/lib/devices/unifi/unifi-logger.d.ts +5 -5
- package/lib/devices/unifi/unifi-logger.js +9 -8
- package/lib/devices/unifi/unifi-protect.d.ts +38 -7
- package/lib/devices/unifi/unifi-protect.js +199 -66
- package/lib/enums/DeviceCapability.d.ts +1 -0
- package/lib/enums/DeviceCapability.js +1 -0
- package/lib/enums/commandType.d.ts +1 -0
- package/lib/enums/commandType.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 +23 -0
- package/lib/interfaces/baseDevices/iAirQualityCollector.js +2 -0
- package/lib/interfaces/baseDevices/iAirQualitySensor.d.ts +97 -0
- package/lib/interfaces/baseDevices/iAirQualitySensor.js +7 -0
- package/lib/interfaces/baseDevices/index.d.ts +2 -0
- package/lib/interfaces/baseDevices/index.js +2 -0
- package/lib/interfaces/iBlockAutomaticHandler.d.ts +4 -0
- package/lib/interfaces/iPersist.d.ts +6 -1
- package/lib/services/ac/ac-device.js +11 -0
- package/lib/services/blockAutomaticHandler.d.ts +11 -0
- package/lib/services/blockAutomaticHandler.js +17 -0
- package/lib/services/dbo/postgreSqlPersist.d.ts +3 -1
- package/lib/services/dbo/postgreSqlPersist.js +34 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseAction } from './baseAction';
|
|
2
|
+
import { CommandType } from '../enums';
|
|
3
|
+
import { iAirQualityCollector, iAirQualityReadings } from '../interfaces';
|
|
4
|
+
export declare class AirQualitySensorChangeAction extends BaseAction {
|
|
5
|
+
/** @inheritDoc */
|
|
6
|
+
type: CommandType;
|
|
7
|
+
/**
|
|
8
|
+
* The new readings of the sensor
|
|
9
|
+
*/
|
|
10
|
+
readonly newReadings: iAirQualityReadings;
|
|
11
|
+
/**
|
|
12
|
+
* The sensor that triggered the action
|
|
13
|
+
*/
|
|
14
|
+
readonly sensor: iAirQualityCollector;
|
|
15
|
+
constructor(sensor: iAirQualityCollector, newReadings: iAirQualityReadings);
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AirQualitySensorChangeAction = void 0;
|
|
4
|
+
const baseAction_1 = require("./baseAction");
|
|
5
|
+
const enums_1 = require("../enums");
|
|
6
|
+
class AirQualitySensorChangeAction extends baseAction_1.BaseAction {
|
|
7
|
+
constructor(sensor, newReadings) {
|
|
8
|
+
super(enums_1.CommandSource.Automatic, `${sensor.customName} detected an air quality index of ${newReadings.aqi}`);
|
|
9
|
+
/** @inheritDoc */
|
|
10
|
+
this.type = enums_1.CommandType.AirQualitySensorChangeAction;
|
|
11
|
+
this.newReadings = newReadings;
|
|
12
|
+
this.sensor = sensor;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.AirQualitySensorChangeAction = AirQualitySensorChangeAction;
|
package/lib/action/index.d.ts
CHANGED
package/lib/action/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DingSensorAction = exports.HandleChangeAction = exports.PresenceGroupAnyMovementAction = exports.BatteryLevelChangeAction = exports.ActuatorChangeAction = exports.TemperatureSensorChangeAction = exports.ShutterPositionChangedAction = exports.PresenceGroupFirstEnterAction = exports.PresenceGroupLastLeftAction = exports.MotionSensorAction = exports.HumiditySensorChangeAction = exports.BaseAction = void 0;
|
|
3
|
+
exports.DingSensorAction = exports.HandleChangeAction = exports.PresenceGroupAnyMovementAction = exports.BatteryLevelChangeAction = exports.ActuatorChangeAction = exports.TemperatureSensorChangeAction = exports.ShutterPositionChangedAction = exports.PresenceGroupFirstEnterAction = exports.PresenceGroupLastLeftAction = exports.MotionSensorAction = exports.HumiditySensorChangeAction = exports.BaseAction = exports.AirQualitySensorChangeAction = void 0;
|
|
4
|
+
var airQualitySensorChangeAction_1 = require("./airQualitySensorChangeAction");
|
|
5
|
+
Object.defineProperty(exports, "AirQualitySensorChangeAction", { enumerable: true, get: function () { return airQualitySensorChangeAction_1.AirQualitySensorChangeAction; } });
|
|
4
6
|
var baseAction_1 = require("./baseAction");
|
|
5
7
|
Object.defineProperty(exports, "BaseAction", { enumerable: true, get: function () { return baseAction_1.BaseAction; } });
|
|
6
8
|
var humiditySensorChangeAction_1 = require("./humiditySensorChangeAction");
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { iAirQualityCollector, iAirQualityReadings, iAirQualitySensor } from '../../interfaces';
|
|
2
|
+
import { AirQualitySensorChangeAction } from '../../action';
|
|
3
|
+
export declare class AirQualitySensor implements iAirQualitySensor {
|
|
4
|
+
private readonly _device;
|
|
5
|
+
/** @inheritDoc */
|
|
6
|
+
readonly jsonOmitKeys: string[];
|
|
7
|
+
/** @inheritDoc */
|
|
8
|
+
lastSeen: number;
|
|
9
|
+
private readonly _readings;
|
|
10
|
+
private _airQualityCallbacks;
|
|
11
|
+
private readonly _persistAirQualitySensorInterval;
|
|
12
|
+
constructor(_device: iAirQualityCollector);
|
|
13
|
+
/** @inheritDoc */
|
|
14
|
+
get readings(): iAirQualityReadings;
|
|
15
|
+
/** @inheritDoc */
|
|
16
|
+
update(readings: Partial<iAirQualityReadings>): void;
|
|
17
|
+
/** @inheritDoc */
|
|
18
|
+
reports(metric: keyof iAirQualityReadings): boolean;
|
|
19
|
+
/** @inheritDoc */
|
|
20
|
+
persist(): void;
|
|
21
|
+
/** @inheritDoc */
|
|
22
|
+
addAirQualityCallback(pCallback: (action: AirQualitySensorChangeAction) => void): void;
|
|
23
|
+
/** @inheritDoc */
|
|
24
|
+
dispose(): void;
|
|
25
|
+
/** @inheritDoc */
|
|
26
|
+
toJSON(): Partial<AirQualitySensor>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AirQualitySensor = 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 AirQualitySensor {
|
|
9
|
+
constructor(_device) {
|
|
10
|
+
this._device = _device;
|
|
11
|
+
/** @inheritDoc */
|
|
12
|
+
this.jsonOmitKeys = ['_device'];
|
|
13
|
+
/** @inheritDoc */
|
|
14
|
+
this.lastSeen = 0;
|
|
15
|
+
this._readings = {
|
|
16
|
+
aqi: interfaces_1.UNDEFINED_AIR_QUALITY_VALUE,
|
|
17
|
+
co2: interfaces_1.UNDEFINED_AIR_QUALITY_VALUE,
|
|
18
|
+
nox: interfaces_1.UNDEFINED_AIR_QUALITY_VALUE,
|
|
19
|
+
pm1p0: interfaces_1.UNDEFINED_AIR_QUALITY_VALUE,
|
|
20
|
+
pm2p5: interfaces_1.UNDEFINED_AIR_QUALITY_VALUE,
|
|
21
|
+
pm4p0: interfaces_1.UNDEFINED_AIR_QUALITY_VALUE,
|
|
22
|
+
pm10p0: interfaces_1.UNDEFINED_AIR_QUALITY_VALUE,
|
|
23
|
+
tvoc: interfaces_1.UNDEFINED_AIR_QUALITY_VALUE,
|
|
24
|
+
vape: interfaces_1.UNDEFINED_AIR_QUALITY_VALUE,
|
|
25
|
+
voc: interfaces_1.UNDEFINED_AIR_QUALITY_VALUE,
|
|
26
|
+
};
|
|
27
|
+
this._airQualityCallbacks = [];
|
|
28
|
+
this._persistAirQualitySensorInterval = utils_1.Utils.guardedInterval(() => {
|
|
29
|
+
this.persist();
|
|
30
|
+
}, 5 * 60 * 1000, this, false);
|
|
31
|
+
}
|
|
32
|
+
/** @inheritDoc */
|
|
33
|
+
get readings() {
|
|
34
|
+
return { ...this._readings };
|
|
35
|
+
}
|
|
36
|
+
/** @inheritDoc */
|
|
37
|
+
update(readings) {
|
|
38
|
+
this.lastSeen = utils_1.Utils.nowMS();
|
|
39
|
+
let changed = false;
|
|
40
|
+
for (const [key, value] of Object.entries(readings)) {
|
|
41
|
+
if (value === undefined || this._readings[key] === value) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
this._readings[key] = value;
|
|
45
|
+
changed = true;
|
|
46
|
+
}
|
|
47
|
+
if (!changed) {
|
|
48
|
+
// The controller repeats unchanged readings every few seconds --> don't bother the consumers with those.
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const snapshot = this.readings;
|
|
52
|
+
for (const cb of this._airQualityCallbacks) {
|
|
53
|
+
cb(new action_1.AirQualitySensorChangeAction(this._device, snapshot));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** @inheritDoc */
|
|
57
|
+
reports(metric) {
|
|
58
|
+
return this._readings[metric] !== interfaces_1.UNDEFINED_AIR_QUALITY_VALUE;
|
|
59
|
+
}
|
|
60
|
+
/** @inheritDoc */
|
|
61
|
+
persist() {
|
|
62
|
+
var _a;
|
|
63
|
+
if (this.lastSeen === 0) {
|
|
64
|
+
// Nothing was ever reported --> persisting would only write a row of undefined values.
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
(_a = services_1.Persistence.dbo) === null || _a === void 0 ? void 0 : _a.persistAirQualitySensor(this._device);
|
|
68
|
+
}
|
|
69
|
+
/** @inheritDoc */
|
|
70
|
+
addAirQualityCallback(pCallback) {
|
|
71
|
+
this._airQualityCallbacks.push(pCallback);
|
|
72
|
+
if (this.lastSeen > 0) {
|
|
73
|
+
pCallback(new action_1.AirQualitySensorChangeAction(this._device, this.readings));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** @inheritDoc */
|
|
77
|
+
dispose() {
|
|
78
|
+
if (this._persistAirQualitySensorInterval) {
|
|
79
|
+
clearInterval(this._persistAirQualitySensorInterval);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** @inheritDoc */
|
|
83
|
+
toJSON() {
|
|
84
|
+
return utils_1.Utils.jsonFilter(this, this.jsonOmitKeys);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.AirQualitySensor = AirQualitySensor;
|
|
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./airQualitySensor"), exports);
|
|
17
18
|
__exportStar(require("./battery"), exports);
|
|
18
19
|
__exportStar(require("./handleSensor"), exports);
|
|
19
20
|
__exportStar(require("./humiditySensor"), exports);
|
|
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./own-unifi-air-quality-sensor"), exports);
|
|
17
18
|
__exportStar(require("./own-unifi-camera"), exports);
|
|
18
19
|
__exportStar(require("./unifi-protect"), exports);
|
|
19
20
|
__exportStar(require("./unifi-access"), exports);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { ProtectSensorConfig, Sensor } from 'unifi-protect';
|
|
2
|
+
import { iAirQualityCollector, iAirQualityReadings, iAirQualitySensor, iHumidityCollector, iHumiditySensor, iTemperatureCollector } from '../../interfaces';
|
|
3
|
+
import { AirQualitySensorChangeAction, HumiditySensorChangeAction, TemperatureSensorChangeAction } from '../../action';
|
|
4
|
+
import { TemperatureSensor } from '../sharedFunctions';
|
|
5
|
+
import { RoomBaseDevice } from '../RoomBaseDevice';
|
|
6
|
+
/**
|
|
7
|
+
* A UniFi Protect "UP Air Quality" sensor.
|
|
8
|
+
*
|
|
9
|
+
* The device reports temperature and humidity alongside its air quality metrics, so it acts as all three
|
|
10
|
+
* collectors at once and its temperature/humidity history lands in the database like any other sensor.
|
|
11
|
+
*/
|
|
12
|
+
export declare class OwnUnifiAirQualitySensor extends RoomBaseDevice implements iTemperatureCollector, iHumidityCollector, iAirQualityCollector {
|
|
13
|
+
/**
|
|
14
|
+
* The name of the sensor as written in Unifi-Protect
|
|
15
|
+
*/
|
|
16
|
+
readonly unifiSensorName: string;
|
|
17
|
+
/**
|
|
18
|
+
* The human readable name of this device
|
|
19
|
+
*/
|
|
20
|
+
readonly name: string;
|
|
21
|
+
/** @inheritDoc */
|
|
22
|
+
temperatureSensor: TemperatureSensor;
|
|
23
|
+
/** @inheritDoc */
|
|
24
|
+
humiditySensor: iHumiditySensor;
|
|
25
|
+
/** @inheritDoc */
|
|
26
|
+
airQualitySensor: iAirQualitySensor;
|
|
27
|
+
protected _lastUpdate: Date;
|
|
28
|
+
private _sensor;
|
|
29
|
+
private _lastReportedTemperature;
|
|
30
|
+
private _lastReportedHumidity;
|
|
31
|
+
constructor(name: string, roomName: string, unifiSensorName: string);
|
|
32
|
+
/**
|
|
33
|
+
* The point in time this device last reported a reading.
|
|
34
|
+
* @returns The timestamp of the last reading
|
|
35
|
+
*/
|
|
36
|
+
get lastUpdate(): Date;
|
|
37
|
+
/** @inheritDoc */
|
|
38
|
+
get airQuality(): iAirQualityReadings;
|
|
39
|
+
/** @inheritDoc */
|
|
40
|
+
get roomTemperature(): number;
|
|
41
|
+
/** @inheritDoc */
|
|
42
|
+
set roomTemperature(value: number);
|
|
43
|
+
/** @inheritDoc */
|
|
44
|
+
get humidity(): number;
|
|
45
|
+
/** @inheritDoc */
|
|
46
|
+
get iTemperature(): number;
|
|
47
|
+
/** @inheritDoc */
|
|
48
|
+
get sTemperature(): string;
|
|
49
|
+
/**
|
|
50
|
+
* Binds this device to its live Unifi-Protect projection and applies the current readings.
|
|
51
|
+
* @param sensor - The projection of the matching Unifi sensor
|
|
52
|
+
*/
|
|
53
|
+
initialize(sensor: Sensor): void;
|
|
54
|
+
/**
|
|
55
|
+
* Applies the readings of the given sensor configuration.
|
|
56
|
+
* @param config - The current configuration of the Unifi sensor
|
|
57
|
+
*/
|
|
58
|
+
update(config: ProtectSensorConfig): void;
|
|
59
|
+
/** @inheritDoc */
|
|
60
|
+
addAirQualityCallback(pCallback: (action: AirQualitySensorChangeAction) => void): void;
|
|
61
|
+
/** @inheritDoc */
|
|
62
|
+
addHumidityCallback(pCallback: (action: HumiditySensorChangeAction) => void): void;
|
|
63
|
+
/** @inheritDoc */
|
|
64
|
+
addTempChangeCallback(pCallback: (action: TemperatureSensorChangeAction) => void): void;
|
|
65
|
+
/** @inheritDoc */
|
|
66
|
+
onTemperaturChange(newTemperatur: number): void;
|
|
67
|
+
/** @inheritDoc */
|
|
68
|
+
dispose(): void;
|
|
69
|
+
/**
|
|
70
|
+
* Reads a single metric out of the controllers air quality readings.
|
|
71
|
+
*
|
|
72
|
+
* Kept structural on purpose: the controller reports `nox`, which the library types do not name,
|
|
73
|
+
* and a metric the device does not measure arrives with a `null` value. The value is rounded to one
|
|
74
|
+
* decimal, as the last digits of the raw reading are sensor jitter that would count as a change on
|
|
75
|
+
* every single update.
|
|
76
|
+
* @param airQuality - The air quality readings of the sensor
|
|
77
|
+
* @param metric - The name of the metric to read
|
|
78
|
+
* @returns The measured value, or undefined if the device does not report it
|
|
79
|
+
*/
|
|
80
|
+
private static metricValue;
|
|
81
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OwnUnifiAirQualitySensor = void 0;
|
|
4
|
+
const sharedFunctions_1 = require("../sharedFunctions");
|
|
5
|
+
const enums_1 = require("../../enums");
|
|
6
|
+
const DeviceInfo_1 = require("../DeviceInfo");
|
|
7
|
+
const devices_1 = require("../devices");
|
|
8
|
+
const RoomBaseDevice_1 = require("../RoomBaseDevice");
|
|
9
|
+
const utils_1 = require("../../utils");
|
|
10
|
+
/**
|
|
11
|
+
* A UniFi Protect "UP Air Quality" sensor.
|
|
12
|
+
*
|
|
13
|
+
* The device reports temperature and humidity alongside its air quality metrics, so it acts as all three
|
|
14
|
+
* collectors at once and its temperature/humidity history lands in the database like any other sensor.
|
|
15
|
+
*/
|
|
16
|
+
class OwnUnifiAirQualitySensor extends RoomBaseDevice_1.RoomBaseDevice {
|
|
17
|
+
constructor(name, roomName, unifiSensorName) {
|
|
18
|
+
const info = new DeviceInfo_1.DeviceInfo();
|
|
19
|
+
info.fullName = `Air Quality ${roomName} ${name}`;
|
|
20
|
+
info.customName = `Air Quality ${name}`;
|
|
21
|
+
info.room = roomName;
|
|
22
|
+
const allDevicesKey = `unifi-air-quality-${roomName}-${name}`;
|
|
23
|
+
info.allDevicesKey = allDevicesKey;
|
|
24
|
+
super(info, enums_1.DeviceType.UnifiAirQualitySensor);
|
|
25
|
+
/** @inheritDoc */
|
|
26
|
+
this.temperatureSensor = new sharedFunctions_1.TemperatureSensor(this);
|
|
27
|
+
/** @inheritDoc */
|
|
28
|
+
this.humiditySensor = new sharedFunctions_1.HumiditySensor(this);
|
|
29
|
+
/** @inheritDoc */
|
|
30
|
+
this.airQualitySensor = new sharedFunctions_1.AirQualitySensor(this);
|
|
31
|
+
this._lastUpdate = new Date(0);
|
|
32
|
+
// @ts-expect-error Sensor-Projektion wird später verwendet
|
|
33
|
+
this._sensor = null;
|
|
34
|
+
this._lastReportedTemperature = undefined;
|
|
35
|
+
this._lastReportedHumidity = undefined;
|
|
36
|
+
this.deviceCapabilities.push(enums_1.DeviceCapability.temperatureSensor);
|
|
37
|
+
this.deviceCapabilities.push(enums_1.DeviceCapability.humiditySensor);
|
|
38
|
+
this.deviceCapabilities.push(enums_1.DeviceCapability.airQualitySensor);
|
|
39
|
+
this.name = name;
|
|
40
|
+
this.unifiSensorName = unifiSensorName;
|
|
41
|
+
devices_1.Devices.alLDevices[allDevicesKey] = this;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The point in time this device last reported a reading.
|
|
45
|
+
* @returns The timestamp of the last reading
|
|
46
|
+
*/
|
|
47
|
+
get lastUpdate() {
|
|
48
|
+
return this._lastUpdate;
|
|
49
|
+
}
|
|
50
|
+
/** @inheritDoc */
|
|
51
|
+
get airQuality() {
|
|
52
|
+
return this.airQualitySensor.readings;
|
|
53
|
+
}
|
|
54
|
+
/** @inheritDoc */
|
|
55
|
+
get roomTemperature() {
|
|
56
|
+
return this.temperatureSensor.roomTemperature;
|
|
57
|
+
}
|
|
58
|
+
/** @inheritDoc */
|
|
59
|
+
set roomTemperature(value) {
|
|
60
|
+
this.temperatureSensor.roomTemperature = value;
|
|
61
|
+
}
|
|
62
|
+
/** @inheritDoc */
|
|
63
|
+
get humidity() {
|
|
64
|
+
return this.humiditySensor.humidity;
|
|
65
|
+
}
|
|
66
|
+
/** @inheritDoc */
|
|
67
|
+
get iTemperature() {
|
|
68
|
+
return this.temperatureSensor.temperature;
|
|
69
|
+
}
|
|
70
|
+
/** @inheritDoc */
|
|
71
|
+
get sTemperature() {
|
|
72
|
+
return `${this.temperatureSensor.temperature}°C`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Binds this device to its live Unifi-Protect projection and applies the current readings.
|
|
76
|
+
* @param sensor - The projection of the matching Unifi sensor
|
|
77
|
+
*/
|
|
78
|
+
initialize(sensor) {
|
|
79
|
+
this._sensor = sensor;
|
|
80
|
+
this.update(sensor.config);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Applies the readings of the given sensor configuration.
|
|
84
|
+
* @param config - The current configuration of the Unifi sensor
|
|
85
|
+
*/
|
|
86
|
+
update(config) {
|
|
87
|
+
const airQuality = config.airQuality;
|
|
88
|
+
this._lastUpdate = new Date();
|
|
89
|
+
// The controller repeats unchanged readings every few seconds, so only a real change wakes the consumers.
|
|
90
|
+
const temperature = OwnUnifiAirQualitySensor.metricValue(airQuality, 'temperature');
|
|
91
|
+
if (temperature !== undefined) {
|
|
92
|
+
if (temperature !== this._lastReportedTemperature) {
|
|
93
|
+
this._lastReportedTemperature = temperature;
|
|
94
|
+
this.temperatureSensor.temperature = temperature;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Only the setter refreshes lastSeen, and a stale one makes the sensor discard its value after an hour.
|
|
98
|
+
this.temperatureSensor.lastSeen = utils_1.Utils.nowMS();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const humidity = OwnUnifiAirQualitySensor.metricValue(airQuality, 'humidity');
|
|
102
|
+
if (humidity !== undefined && humidity !== this._lastReportedHumidity) {
|
|
103
|
+
this._lastReportedHumidity = humidity;
|
|
104
|
+
this.humiditySensor.humidity = humidity;
|
|
105
|
+
}
|
|
106
|
+
this.airQualitySensor.update({
|
|
107
|
+
aqi: OwnUnifiAirQualitySensor.metricValue(airQuality, 'aqi'),
|
|
108
|
+
co2: OwnUnifiAirQualitySensor.metricValue(airQuality, 'co2'),
|
|
109
|
+
nox: OwnUnifiAirQualitySensor.metricValue(airQuality, 'nox'),
|
|
110
|
+
pm1p0: OwnUnifiAirQualitySensor.metricValue(airQuality, 'pm1p0'),
|
|
111
|
+
pm2p5: OwnUnifiAirQualitySensor.metricValue(airQuality, 'pm2p5'),
|
|
112
|
+
pm4p0: OwnUnifiAirQualitySensor.metricValue(airQuality, 'pm4p0'),
|
|
113
|
+
pm10p0: OwnUnifiAirQualitySensor.metricValue(airQuality, 'pm10p0'),
|
|
114
|
+
tvoc: OwnUnifiAirQualitySensor.metricValue(airQuality, 'tvoc'),
|
|
115
|
+
vape: OwnUnifiAirQualitySensor.metricValue(airQuality, 'vape'),
|
|
116
|
+
voc: OwnUnifiAirQualitySensor.metricValue(airQuality, 'voc'),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/** @inheritDoc */
|
|
120
|
+
addAirQualityCallback(pCallback) {
|
|
121
|
+
this.airQualitySensor.addAirQualityCallback(pCallback);
|
|
122
|
+
}
|
|
123
|
+
/** @inheritDoc */
|
|
124
|
+
addHumidityCallback(pCallback) {
|
|
125
|
+
this.humiditySensor.addHumidityCallback(pCallback);
|
|
126
|
+
}
|
|
127
|
+
/** @inheritDoc */
|
|
128
|
+
addTempChangeCallback(pCallback) {
|
|
129
|
+
this.temperatureSensor.addTempChangeCallback(pCallback);
|
|
130
|
+
}
|
|
131
|
+
/** @inheritDoc */
|
|
132
|
+
onTemperaturChange(newTemperatur) {
|
|
133
|
+
this.roomTemperature = newTemperatur;
|
|
134
|
+
}
|
|
135
|
+
/** @inheritDoc */
|
|
136
|
+
dispose() {
|
|
137
|
+
this.temperatureSensor.dispose();
|
|
138
|
+
this.humiditySensor.dispose();
|
|
139
|
+
this.airQualitySensor.dispose();
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Reads a single metric out of the controllers air quality readings.
|
|
143
|
+
*
|
|
144
|
+
* Kept structural on purpose: the controller reports `nox`, which the library types do not name,
|
|
145
|
+
* and a metric the device does not measure arrives with a `null` value. The value is rounded to one
|
|
146
|
+
* decimal, as the last digits of the raw reading are sensor jitter that would count as a change on
|
|
147
|
+
* every single update.
|
|
148
|
+
* @param airQuality - The air quality readings of the sensor
|
|
149
|
+
* @param metric - The name of the metric to read
|
|
150
|
+
* @returns The measured value, or undefined if the device does not report it
|
|
151
|
+
*/
|
|
152
|
+
static metricValue(airQuality, metric) {
|
|
153
|
+
if (typeof airQuality !== 'object' || airQuality === null) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
const reading = Reflect.get(airQuality, metric);
|
|
157
|
+
if (typeof reading !== 'object' || reading === null) {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
const value = Reflect.get(reading, 'value');
|
|
161
|
+
return typeof value === 'number' ? utils_1.Utils.round(value, 1) : undefined;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.OwnUnifiAirQualitySensor = OwnUnifiAirQualitySensor;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CameraDevice } from '../index';
|
|
2
|
-
import {
|
|
2
|
+
import type { Camera, TypedEvent } from 'unifi-protect';
|
|
3
3
|
export declare class OwnUnifiCamera extends CameraDevice {
|
|
4
4
|
/**
|
|
5
5
|
* The name of the camera in Unifi
|
|
@@ -13,14 +13,15 @@ export declare class OwnUnifiCamera extends CameraDevice {
|
|
|
13
13
|
rtspStreamLink: string;
|
|
14
14
|
/** @inheritDoc */
|
|
15
15
|
readonly currentImageLink: string;
|
|
16
|
-
private
|
|
16
|
+
private _camera;
|
|
17
17
|
constructor(name: string, roomName: string, unifiCameraName: string);
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Handles a realtime event the NVR attributed to this camera.
|
|
20
|
+
* @param event - The typed event as classified by the NVR client
|
|
20
21
|
*/
|
|
21
|
-
update(
|
|
22
|
+
update(event: TypedEvent): void;
|
|
22
23
|
private checkForMotionUpdate;
|
|
23
|
-
initialize(
|
|
24
|
+
initialize(camera: Camera): void;
|
|
24
25
|
protected resetPersonDetectedState(): void;
|
|
25
26
|
protected resetDogDetectedState(): void;
|
|
26
27
|
protected resetMovementDetectedState(): void;
|
|
@@ -14,38 +14,28 @@ class OwnUnifiCamera extends index_1.CameraDevice {
|
|
|
14
14
|
this.rtspStreamLink = '';
|
|
15
15
|
/** @inheritDoc */
|
|
16
16
|
this.currentImageLink = '';
|
|
17
|
-
// @ts-expect-error
|
|
18
|
-
this.
|
|
17
|
+
// @ts-expect-error Kamera-Projektion wird später verwendet
|
|
18
|
+
this._camera = null;
|
|
19
19
|
this.unifiCameraName = unifiCameraName;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* Handles a realtime event the NVR attributed to this camera.
|
|
23
|
+
* @param event - The typed event as classified by the NVR client
|
|
23
24
|
*/
|
|
24
|
-
update(
|
|
25
|
-
this.checkForMotionUpdate(
|
|
25
|
+
update(event) {
|
|
26
|
+
this.checkForMotionUpdate(event);
|
|
26
27
|
this._lastUpdate = new Date();
|
|
27
28
|
}
|
|
28
|
-
checkForMotionUpdate(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const eventAddInfo = baseEvent !== null && baseEvent !== void 0 ? baseEvent : payload;
|
|
32
|
-
const payloadAsEventAdd = payload;
|
|
33
|
-
if (packet.header.modelKey !== 'smartDetectObject' &&
|
|
34
|
-
(packet.header.modelKey !== 'event' ||
|
|
35
|
-
!['smartDetectLine', 'smartDetectZone'].includes(eventAddInfo.type) ||
|
|
36
|
-
!((_a = payloadAsEventAdd.smartDetectTypes) !== null && _a !== void 0 ? _a : []).length)) {
|
|
37
|
-
// this.log(LogLevel.Debug, `Ignored event: ${JSON.stringify(packet)}`);
|
|
38
|
-
// this.log(LogLevel.Debug, `Ignored event initial Info: ${JSON.stringify(baseEvent)}`);
|
|
29
|
+
checkForMotionUpdate(event) {
|
|
30
|
+
if (event.kind !== 'smartDetect' || !event.objectTypes.length) {
|
|
31
|
+
// this.log(LogLevel.Debug, `Ignored event: ${JSON.stringify(event)}`);
|
|
39
32
|
return;
|
|
40
33
|
}
|
|
41
|
-
this.log(enums_1.LogLevel.Debug, `Update for "${
|
|
42
|
-
const
|
|
43
|
-
? [payloadAsEventAdd.type]
|
|
44
|
-
: ((_b = payloadAsEventAdd === null || payloadAsEventAdd === void 0 ? void 0 : payloadAsEventAdd.smartDetectTypes) !== null && _b !== void 0 ? _b : []);
|
|
45
|
-
for (const smartDetectType of detectedTypes) {
|
|
34
|
+
this.log(enums_1.LogLevel.Debug, `Update for "${event.kind}" to value: ${event.objectTypes.join(', ')}`);
|
|
35
|
+
for (const smartDetectType of event.objectTypes) {
|
|
46
36
|
switch (smartDetectType) {
|
|
47
37
|
case 'licensePlate':
|
|
48
|
-
this.log(enums_1.LogLevel.Debug, `Detected "licensePlate" Data: ${JSON.stringify(
|
|
38
|
+
this.log(enums_1.LogLevel.Debug, `Detected "licensePlate" Data: ${JSON.stringify(event.metadata)}`);
|
|
49
39
|
break;
|
|
50
40
|
case 'person':
|
|
51
41
|
this.onNewPersonDetectedValue(true, enums_1.CommandSource.Automatic);
|
|
@@ -53,8 +43,8 @@ class OwnUnifiCamera extends index_1.CameraDevice {
|
|
|
53
43
|
}
|
|
54
44
|
}
|
|
55
45
|
}
|
|
56
|
-
initialize(
|
|
57
|
-
this.
|
|
46
|
+
initialize(camera) {
|
|
47
|
+
this._camera = camera;
|
|
58
48
|
}
|
|
59
49
|
resetPersonDetectedState() {
|
|
60
50
|
// Nothing
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type ProtectModule = typeof import('unifi-protect');
|
|
2
|
+
/**
|
|
3
|
+
* Loads the ESM-only `unifi-protect` package.
|
|
4
|
+
*
|
|
5
|
+
* Since v5 the package exposes an "import" condition only, so `require()` fails with
|
|
6
|
+
* ERR_PACKAGE_PATH_NOT_EXPORTED. The `Function` indirection keeps TypeScript from downleveling
|
|
7
|
+
* the dynamic import into a `require()` call while this project still emits CommonJS.
|
|
8
|
+
* @returns The module namespace, loaded once and cached.
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadProtectModule(): Promise<ProtectModule>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadProtectModule = loadProtectModule;
|
|
4
|
+
let modulePromise = null;
|
|
5
|
+
/**
|
|
6
|
+
* Loads the ESM-only `unifi-protect` package.
|
|
7
|
+
*
|
|
8
|
+
* Since v5 the package exposes an "import" condition only, so `require()` fails with
|
|
9
|
+
* ERR_PACKAGE_PATH_NOT_EXPORTED. The `Function` indirection keeps TypeScript from downleveling
|
|
10
|
+
* the dynamic import into a `require()` call while this project still emits CommonJS.
|
|
11
|
+
* @returns The module namespace, loaded once and cached.
|
|
12
|
+
*/
|
|
13
|
+
function loadProtectModule() {
|
|
14
|
+
modulePromise !== null && modulePromise !== void 0 ? modulePromise : (modulePromise = Function('specifier', 'return import(specifier)')('unifi-protect'));
|
|
15
|
+
return modulePromise;
|
|
16
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { ProtectLogging } from 'unifi-protect';
|
|
1
|
+
import type { ProtectLogging } from 'unifi-protect';
|
|
2
2
|
import { LogSource } from '../../enums';
|
|
3
3
|
export declare class UnifiLogger implements ProtectLogging {
|
|
4
4
|
private readonly source;
|
|
5
5
|
constructor(source: LogSource);
|
|
6
|
-
debug(message: string, ...
|
|
7
|
-
error(message: string, ...
|
|
8
|
-
info(message: string, ...
|
|
9
|
-
warn(message: string, ...
|
|
6
|
+
debug(message: string, ...parameters: unknown[]): void;
|
|
7
|
+
error(message: string, ...parameters: unknown[]): void;
|
|
8
|
+
info(message: string, ...parameters: unknown[]): void;
|
|
9
|
+
warn(message: string, ...parameters: unknown[]): void;
|
|
10
10
|
}
|
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.UnifiLogger = void 0;
|
|
4
|
+
const node_util_1 = require("node:util");
|
|
4
5
|
const logging_1 = require("../../logging");
|
|
5
6
|
const enums_1 = require("../../enums");
|
|
6
7
|
class UnifiLogger {
|
|
7
8
|
constructor(source) {
|
|
8
9
|
this.source = source;
|
|
9
10
|
}
|
|
10
|
-
debug(message, ...
|
|
11
|
-
logging_1.ServerLogService.writeLog(enums_1.LogLevel.Debug, message, {
|
|
11
|
+
debug(message, ...parameters) {
|
|
12
|
+
logging_1.ServerLogService.writeLog(enums_1.LogLevel.Debug, (0, node_util_1.format)(message, ...parameters), {
|
|
12
13
|
source: this.source,
|
|
13
14
|
});
|
|
14
15
|
}
|
|
15
|
-
error(message, ...
|
|
16
|
-
logging_1.ServerLogService.writeLog(enums_1.LogLevel.Error, message, {
|
|
16
|
+
error(message, ...parameters) {
|
|
17
|
+
logging_1.ServerLogService.writeLog(enums_1.LogLevel.Error, (0, node_util_1.format)(message, ...parameters), {
|
|
17
18
|
source: this.source,
|
|
18
19
|
});
|
|
19
20
|
}
|
|
20
|
-
info(message, ...
|
|
21
|
-
logging_1.ServerLogService.writeLog(enums_1.LogLevel.Info, message, {
|
|
21
|
+
info(message, ...parameters) {
|
|
22
|
+
logging_1.ServerLogService.writeLog(enums_1.LogLevel.Info, (0, node_util_1.format)(message, ...parameters), {
|
|
22
23
|
source: this.source,
|
|
23
24
|
});
|
|
24
25
|
}
|
|
25
|
-
warn(message, ...
|
|
26
|
-
logging_1.ServerLogService.writeLog(enums_1.LogLevel.Warn, message, {
|
|
26
|
+
warn(message, ...parameters) {
|
|
27
|
+
logging_1.ServerLogService.writeLog(enums_1.LogLevel.Warn, (0, node_util_1.format)(message, ...parameters), {
|
|
27
28
|
source: this.source,
|
|
28
29
|
});
|
|
29
30
|
}
|