2634 lines
146 KiB
JavaScript
2634 lines
146 KiB
JavaScript
"use strict";
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.EufySecurity = void 0;
|
|
const tiny_typed_emitter_1 = require("tiny-typed-emitter");
|
|
const fse = __importStar(require("fs-extra"));
|
|
const path = __importStar(require("path"));
|
|
const events_1 = __importDefault(require("events"));
|
|
const api_1 = require("./http/api");
|
|
const station_1 = require("./http/station");
|
|
const types_1 = require("./http/types");
|
|
const service_1 = require("./push/service");
|
|
const device_1 = require("./http/device");
|
|
const types_2 = require("./p2p/types");
|
|
const utils_1 = require("./utils");
|
|
const error_1 = require("./error");
|
|
const _1 = require(".");
|
|
const error_2 = require("./http/error");
|
|
const types_3 = require("./push/types");
|
|
const service_2 = require("./mqtt/service");
|
|
const const_1 = require("./http/const");
|
|
const utils_2 = require("./http/utils");
|
|
const logging_1 = require("./logging");
|
|
const typescript_logging_1 = require("typescript-logging");
|
|
const utils_3 = require("./p2p/utils");
|
|
class EufySecurity extends tiny_typed_emitter_1.TypedEmitter {
|
|
config;
|
|
api;
|
|
houses = {};
|
|
stations = {};
|
|
devices = {};
|
|
P2P_REFRESH_INTERVAL_MIN = 720;
|
|
cameraMaxLivestreamSeconds = 30;
|
|
cameraStationLivestreamTimeout = new Map();
|
|
pushService;
|
|
mqttService;
|
|
pushCloudRegistered = false;
|
|
pushCloudChecked = false;
|
|
persistentFile;
|
|
persistentData = {
|
|
country: "",
|
|
openudid: "",
|
|
serial_number: "",
|
|
push_credentials: undefined,
|
|
push_persistentIds: [],
|
|
login_hash: "",
|
|
version: "",
|
|
httpApi: undefined
|
|
};
|
|
connected = false;
|
|
retries = 0;
|
|
refreshEufySecurityCloudTimeout;
|
|
refreshEufySecurityP2PTimeout = {};
|
|
deviceSnoozeTimeout = {};
|
|
loadingEmitter = new events_1.default();
|
|
stationsLoaded = (0, utils_1.waitForEvent)(this.loadingEmitter, "stations loaded");
|
|
devicesLoaded = (0, utils_1.waitForEvent)(this.loadingEmitter, "devices loaded");
|
|
constructor(config, log = logging_1.dummyLogger) {
|
|
super();
|
|
this.config = config;
|
|
logging_1.InternalLogger.logger = log;
|
|
}
|
|
static async initialize(config, log = logging_1.dummyLogger) {
|
|
const eufySecurity = new EufySecurity(config, log);
|
|
await eufySecurity._initializeInternals();
|
|
return eufySecurity;
|
|
}
|
|
async _initializeInternals() {
|
|
if (this.config.logging) {
|
|
if (this.config.logging.level !== undefined && typeof this.config.logging.level === "number" && Object.values(typescript_logging_1.LogLevel).includes(this.config.logging.level))
|
|
(0, logging_1.setLoggingLevel)("all", this.config.logging.level);
|
|
if (this.config.logging.categories !== undefined && Array.isArray(this.config.logging.categories)) {
|
|
for (const category of this.config.logging.categories) {
|
|
if (typeof category === "object" &&
|
|
"category" in category &&
|
|
"level" in category &&
|
|
typeof category.level === "number" &&
|
|
Object.values(typescript_logging_1.LogLevel).includes(category.level) &&
|
|
typeof category.category === "string" &&
|
|
["main", "http", "p2p", "push", "mqtt"].includes(category.category.toLowerCase())) {
|
|
(0, logging_1.setLoggingLevel)(category.category.toLocaleLowerCase(), category.level);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (this.config.country === undefined) {
|
|
this.config.country = "US";
|
|
}
|
|
else {
|
|
this.config.country = this.config.country.toUpperCase();
|
|
}
|
|
if (this.config.language === undefined) {
|
|
this.config.language = "en";
|
|
}
|
|
if (this.config.eventDurationSeconds === undefined) {
|
|
this.config.eventDurationSeconds = 10;
|
|
}
|
|
if (this.config.p2pConnectionSetup === undefined) {
|
|
this.config.p2pConnectionSetup = types_2.P2PConnectionType.QUICKEST;
|
|
}
|
|
else if (!Object.values(types_2.P2PConnectionType).includes(this.config.p2pConnectionSetup)) {
|
|
this.config.p2pConnectionSetup = types_2.P2PConnectionType.QUICKEST;
|
|
}
|
|
if (this.config.pollingIntervalMinutes === undefined) {
|
|
this.config.pollingIntervalMinutes = 10;
|
|
}
|
|
if (this.config.acceptInvitations === undefined) {
|
|
this.config.acceptInvitations = false;
|
|
}
|
|
if (this.config.enableEmbeddedPKCS1Support === undefined) {
|
|
this.config.enableEmbeddedPKCS1Support = false;
|
|
}
|
|
if (this.config.deviceConfig === undefined) {
|
|
this.config.deviceConfig = {
|
|
simultaneousDetections: true
|
|
};
|
|
}
|
|
if (this.config.persistentDir === undefined) {
|
|
this.config.persistentDir = path.resolve(__dirname, "../../..");
|
|
}
|
|
else if (!fse.existsSync(this.config.persistentDir)) {
|
|
this.config.persistentDir = path.resolve(__dirname, "../../..");
|
|
}
|
|
if (this.config.persistentData) {
|
|
this.persistentData = JSON.parse(this.config.persistentData);
|
|
}
|
|
else {
|
|
this.persistentFile = path.join(this.config.persistentDir, "persistent.json");
|
|
}
|
|
try {
|
|
if (!this.config.persistentData && fse.statSync(this.persistentFile).isFile()) {
|
|
const fileContent = fse.readFileSync(this.persistentFile, "utf8");
|
|
this.persistentData = JSON.parse(fileContent);
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.debug("No stored data from last exit found", { error: (0, utils_1.getError)(error) });
|
|
}
|
|
logging_1.rootMainLogger.debug("Loaded persistent data", { persistentData: this.persistentData });
|
|
try {
|
|
if (this.persistentData.version !== _1.libVersion) {
|
|
const currentVersion = Number.parseFloat((0, utils_1.removeLastChar)(_1.libVersion, "."));
|
|
const previousVersion = this.persistentData.version !== "" && this.persistentData.version !== undefined ? Number.parseFloat((0, utils_1.removeLastChar)(this.persistentData.version, ".")) : 0;
|
|
logging_1.rootMainLogger.debug("Handling of driver update", { currentVersion: currentVersion, previousVersion: previousVersion });
|
|
if (previousVersion < currentVersion) {
|
|
this.persistentData = (0, utils_1.handleUpdate)(this.persistentData, previousVersion);
|
|
this.persistentData.version = _1.libVersion;
|
|
}
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Handling update - Error", { error: (0, utils_1.getError)(error) });
|
|
}
|
|
if (this.config.trustedDeviceName === undefined || this.config.trustedDeviceName === "") {
|
|
if (this.persistentData.fallbackTrustedDeviceName !== undefined) {
|
|
this.config.trustedDeviceName = this.persistentData.fallbackTrustedDeviceName;
|
|
}
|
|
else {
|
|
const rnd = (0, utils_2.randomNumber)(0, const_1.PhoneModels.length);
|
|
this.persistentData.fallbackTrustedDeviceName = const_1.PhoneModels[rnd];
|
|
this.config.trustedDeviceName = this.persistentData.fallbackTrustedDeviceName;
|
|
}
|
|
}
|
|
if (this.persistentData.login_hash && this.persistentData.login_hash != "") {
|
|
logging_1.rootMainLogger.debug("Load previous login_hash", { login_hash: this.persistentData.login_hash });
|
|
if ((0, utils_1.md5)(`${this.config.username}:${this.config.password}`) != this.persistentData.login_hash) {
|
|
logging_1.rootMainLogger.info("Authentication properties changed, invalidate saved cloud token.");
|
|
this.persistentData.cloud_token = "";
|
|
this.persistentData.cloud_token_expiration = 0;
|
|
this.persistentData.httpApi = undefined;
|
|
}
|
|
}
|
|
else {
|
|
this.persistentData.cloud_token = "";
|
|
this.persistentData.cloud_token_expiration = 0;
|
|
this.persistentData.httpApi = undefined;
|
|
}
|
|
if (this.persistentData.country !== undefined && this.persistentData.country !== "" && this.persistentData.country !== this.config.country) {
|
|
logging_1.rootMainLogger.info("Country property changed, invalidate saved cloud token.");
|
|
this.persistentData.cloud_token = "";
|
|
this.persistentData.cloud_token_expiration = 0;
|
|
this.persistentData.httpApi = undefined;
|
|
}
|
|
if (this.persistentData.httpApi !== undefined && (this.persistentData.httpApi.clientPrivateKey === undefined || this.persistentData.httpApi.clientPrivateKey === "" || this.persistentData.httpApi.serverPublicKey === undefined || this.persistentData.httpApi.serverPublicKey === "")) {
|
|
logging_1.rootMainLogger.debug("Incomplete persistent data for v2 encrypted cloud api communication. Invalidate authenticated session data.");
|
|
this.persistentData.cloud_token = "";
|
|
this.persistentData.cloud_token_expiration = 0;
|
|
this.persistentData.httpApi = undefined;
|
|
}
|
|
this.api = await api_1.HTTPApi.initialize(this.config.country, this.config.username, this.config.password, this.persistentData.httpApi);
|
|
this.api.setLanguage(this.config.language);
|
|
this.api.setPhoneModel(this.config.trustedDeviceName);
|
|
this.api.on("houses", (houses) => this.handleHouses(houses));
|
|
this.api.on("hubs", (hubs) => this.handleHubs(hubs));
|
|
this.api.on("devices", (devices) => this.handleDevices(devices));
|
|
this.api.on("close", () => this.onAPIClose());
|
|
this.api.on("connect", () => this.onAPIConnect());
|
|
this.api.on("captcha request", (id, captcha) => this.onCaptchaRequest(id, captcha));
|
|
this.api.on("auth token invalidated", () => this.onAuthTokenInvalidated());
|
|
this.api.on("tfa request", () => this.onTfaRequest());
|
|
this.api.on("connection error", (error) => this.onAPIConnectionError(error));
|
|
if (this.persistentData.cloud_token && this.persistentData.cloud_token != "" && this.persistentData.cloud_token_expiration) {
|
|
logging_1.rootMainLogger.debug("Load previous token", { token: this.persistentData.cloud_token, tokenExpiration: this.persistentData.cloud_token_expiration, persistentHttpApi: this.persistentData.httpApi });
|
|
this.api.setToken(this.persistentData.cloud_token);
|
|
this.api.setTokenExpiration(new Date(this.persistentData.cloud_token_expiration));
|
|
}
|
|
if (!this.persistentData.openudid || this.persistentData.openudid == "") {
|
|
this.persistentData.openudid = (0, utils_1.generateUDID)();
|
|
logging_1.rootMainLogger.debug("Generated new openudid", { openudid: this.persistentData.openudid });
|
|
}
|
|
this.api.setOpenUDID(this.persistentData.openudid);
|
|
if (!this.persistentData.serial_number || this.persistentData.serial_number == "") {
|
|
this.persistentData.serial_number = (0, utils_1.generateSerialnumber)(12);
|
|
logging_1.rootMainLogger.debug("Generated new serial_number", { serialnumber: this.persistentData.serial_number });
|
|
}
|
|
this.api.setSerialNumber(this.persistentData.serial_number);
|
|
this.pushService = await service_1.PushNotificationService.initialize();
|
|
this.pushService.on("connect", async (token) => {
|
|
this.pushCloudRegistered = await this.api.registerPushToken(token);
|
|
this.pushCloudChecked = await this.api.checkPushToken();
|
|
//TODO: Retry if failed with max retry to not lock account
|
|
if (this.pushCloudRegistered && this.pushCloudChecked) {
|
|
logging_1.rootMainLogger.info("Push notification connection successfully established");
|
|
this.emit("push connect");
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.info("Push notification connection closed");
|
|
this.emit("push close");
|
|
}
|
|
});
|
|
this.pushService.on("credential", (credentials) => {
|
|
this.savePushCredentials(credentials);
|
|
});
|
|
this.pushService.on("message", (message) => this.onPushMessage(message));
|
|
this.pushService.on("close", () => {
|
|
logging_1.rootMainLogger.info("Push notification connection closed");
|
|
this.emit("push close");
|
|
});
|
|
await this.initMQTT();
|
|
}
|
|
async initMQTT() {
|
|
this.mqttService = await service_2.MQTTService.init();
|
|
this.mqttService.on("connect", () => {
|
|
logging_1.rootMainLogger.info("MQTT connection successfully established");
|
|
this.emit("mqtt connect");
|
|
});
|
|
this.mqttService.on("close", () => {
|
|
logging_1.rootMainLogger.info("MQTT connection closed");
|
|
this.emit("mqtt close");
|
|
});
|
|
this.mqttService.on("lock message", (message) => {
|
|
this.getDevice(message.data.data.deviceSn).then((device) => {
|
|
device.processMQTTNotification(message.data.data, this.config.eventDurationSeconds);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
if (!(error instanceof error_1.DeviceNotFoundError)) {
|
|
logging_1.rootMainLogger.error("Lock MQTT Message Error", { error: (0, utils_1.getError)(error) });
|
|
}
|
|
}).finally(() => {
|
|
this.emit("mqtt lock message", message);
|
|
});
|
|
});
|
|
}
|
|
setLoggingLevel(category, level) {
|
|
if (typeof level === "number" &&
|
|
Object.values(typescript_logging_1.LogLevel).includes(level) &&
|
|
typeof category === "string" &&
|
|
["all", "main", "http", "p2p", "push", "mqtt"].includes(category.toLowerCase())) {
|
|
(0, logging_1.setLoggingLevel)(category, level);
|
|
}
|
|
}
|
|
getLoggingLevel(category) {
|
|
if (typeof category === "string" &&
|
|
["all", "main", "http", "p2p", "push", "mqtt"].includes(category.toLowerCase())) {
|
|
return (0, logging_1.getLoggingLevel)(category);
|
|
}
|
|
return -1;
|
|
}
|
|
setInternalLogger(logger) {
|
|
logging_1.InternalLogger.logger = logger;
|
|
}
|
|
getInternalLogger() {
|
|
return logging_1.InternalLogger.logger;
|
|
}
|
|
getPushService() {
|
|
return this.pushService;
|
|
}
|
|
addStation(station) {
|
|
const serial = station.getSerial();
|
|
if (serial && !Object.keys(this.stations).includes(serial)) {
|
|
this.stations[serial] = station;
|
|
this.emit("station added", station);
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.debug(`Station with this serial ${station.getSerial()} exists already and couldn't be added again!`);
|
|
}
|
|
}
|
|
removeStation(station) {
|
|
const serial = station.getSerial();
|
|
if (serial && Object.keys(this.stations).includes(serial)) {
|
|
delete this.stations[serial];
|
|
station.removeAllListeners();
|
|
if (station.isConnected())
|
|
station.close();
|
|
this.emit("station removed", station);
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.debug(`Station with this serial ${station.getSerial()} doesn't exists and couldn't be removed!`);
|
|
}
|
|
}
|
|
async updateStation(hub) {
|
|
if (this.stationsLoaded)
|
|
await this.stationsLoaded;
|
|
if (Object.keys(this.stations).includes(hub.station_sn)) {
|
|
this.stations[hub.station_sn].update(hub);
|
|
if (!this.stations[hub.station_sn].isConnected() && !this.stations[hub.station_sn].isEnergySavingDevice() && this.stations[hub.station_sn].isP2PConnectableDevice()) {
|
|
this.stations[hub.station_sn].setConnectionType(this.config.p2pConnectionSetup);
|
|
logging_1.rootMainLogger.debug(`Updating station cloud data - initiate station connection to get local data over p2p`, { stationSN: hub.station_sn });
|
|
this.stations[hub.station_sn].connect();
|
|
}
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.debug(`Station with this serial ${hub.station_sn} doesn't exists and couldn't be updated!`);
|
|
}
|
|
}
|
|
addDevice(device) {
|
|
const serial = device.getSerial();
|
|
if (serial && !Object.keys(this.devices).includes(serial)) {
|
|
this.devices[serial] = device;
|
|
this.emit("device added", device);
|
|
if (device.isLock())
|
|
this.mqttService.subscribeLock(device.getSerial());
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.debug(`Device with this serial ${device.getSerial()} exists already and couldn't be added again!`);
|
|
}
|
|
}
|
|
removeDevice(device) {
|
|
const serial = device.getSerial();
|
|
if (serial && Object.keys(this.devices).includes(serial)) {
|
|
delete this.devices[serial];
|
|
device.removeAllListeners();
|
|
this.emit("device removed", device);
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.debug(`Device with this serial ${device.getSerial()} doesn't exists and couldn't be removed!`);
|
|
}
|
|
}
|
|
async updateDevice(device) {
|
|
if (this.devicesLoaded)
|
|
await this.devicesLoaded;
|
|
if (Object.keys(this.devices).includes(device.device_sn))
|
|
this.devices[device.device_sn].update(device);
|
|
else
|
|
logging_1.rootMainLogger.debug(`Device with this serial ${device.device_sn} doesn't exists and couldn't be updated!`);
|
|
}
|
|
async getDevices() {
|
|
if (this.devicesLoaded)
|
|
await this.devicesLoaded;
|
|
const arr = [];
|
|
Object.keys(this.devices).forEach((serialNumber) => {
|
|
arr.push(this.devices[serialNumber]);
|
|
});
|
|
return arr;
|
|
}
|
|
async getDevicesFromStation(stationSN) {
|
|
if (this.devicesLoaded)
|
|
await this.devicesLoaded;
|
|
const arr = [];
|
|
Object.keys(this.devices).forEach((serialNumber) => {
|
|
if (this.devices[serialNumber].getStationSerial() === stationSN)
|
|
arr.push(this.devices[serialNumber]);
|
|
});
|
|
return arr;
|
|
}
|
|
async getDevice(deviceSN) {
|
|
if (this.devicesLoaded)
|
|
await this.devicesLoaded;
|
|
if (Object.keys(this.devices).includes(deviceSN))
|
|
return this.devices[deviceSN];
|
|
throw new error_1.DeviceNotFoundError("Device doesn't exists", { context: { device: deviceSN } });
|
|
}
|
|
async getStationDevice(stationSN, channel) {
|
|
if (this.devicesLoaded)
|
|
await this.devicesLoaded;
|
|
for (const device of Object.values(this.devices)) {
|
|
if ((device.getStationSerial() === stationSN && device.getChannel() === channel) || (device.getStationSerial() === stationSN && device.getSerial() === stationSN)) {
|
|
return device;
|
|
}
|
|
}
|
|
throw new error_1.DeviceNotFoundError("No device with passed channel found on station", { context: { station: stationSN, channel: channel } });
|
|
}
|
|
async getStations() {
|
|
if (this.stationsLoaded)
|
|
await this.stationsLoaded;
|
|
const arr = [];
|
|
Object.keys(this.stations).forEach((serialNumber) => {
|
|
arr.push(this.stations[serialNumber]);
|
|
});
|
|
return arr;
|
|
}
|
|
async getStation(stationSN) {
|
|
if (this.stationsLoaded)
|
|
await this.stationsLoaded;
|
|
if (Object.keys(this.stations).includes(stationSN))
|
|
return this.stations[stationSN];
|
|
throw new error_1.StationNotFoundError("Station doesn't exists", { context: { station: stationSN } });
|
|
}
|
|
getApi() {
|
|
return this.api;
|
|
}
|
|
async connectToStation(stationSN, p2pConnectionType = types_2.P2PConnectionType.QUICKEST) {
|
|
const station = await this.getStation(stationSN);
|
|
if (station.isP2PConnectableDevice()) {
|
|
station.setConnectionType(p2pConnectionType);
|
|
logging_1.rootMainLogger.debug(`Explicit request for p2p connection to the station`, { stationSN: station.getSerial() });
|
|
await station.connect();
|
|
}
|
|
}
|
|
async isStationConnected(stationSN) {
|
|
const station = await this.getStation(stationSN);
|
|
return station.isConnected();
|
|
}
|
|
async isStationEnergySavingDevice(stationSN) {
|
|
const station = await this.getStation(stationSN);
|
|
return station.isEnergySavingDevice();
|
|
}
|
|
handleHouses(houses) {
|
|
logging_1.rootMainLogger.debug("Got houses", { houses: houses });
|
|
//TODO: Finish implementation
|
|
this.houses = houses;
|
|
}
|
|
handleHubs(hubs) {
|
|
logging_1.rootMainLogger.debug("Got hubs", { hubs: hubs });
|
|
const stationsSNs = Object.keys(this.stations);
|
|
const newStationsSNs = Object.keys(hubs);
|
|
const promises = [];
|
|
for (const hub of Object.values(hubs)) {
|
|
if (stationsSNs.includes(hub.station_sn)) {
|
|
this.updateStation(hub);
|
|
}
|
|
else {
|
|
if (this.stationsLoaded === undefined)
|
|
this.stationsLoaded = (0, utils_1.waitForEvent)(this.loadingEmitter, "stations loaded");
|
|
let ipAddress;
|
|
if (this.config.stationIPAddresses !== undefined) {
|
|
ipAddress = this.config.stationIPAddresses[hub.station_sn];
|
|
}
|
|
const station = station_1.Station.getInstance(this.api, hub, ipAddress, 0, this.config.enableEmbeddedPKCS1Support);
|
|
promises.push(station.then((station) => {
|
|
try {
|
|
station.on("connect", (station) => this.onStationConnect(station));
|
|
station.on("connection error", (station, error) => this.onStationConnectionError(station, error));
|
|
station.on("close", (station) => this.onStationClose(station));
|
|
station.on("raw device property changed", (deviceSN, params) => this.updateDeviceProperties(deviceSN, params));
|
|
station.on("livestream start", (station, channel, metadata, videostream, audiostream) => this.onStartStationLivestream(station, channel, metadata, videostream, audiostream));
|
|
station.on("livestream stop", (station, channel) => this.onStopStationLivestream(station, channel));
|
|
station.on("livestream error", (station, channel, error) => this.onErrorStationLivestream(station, channel, error));
|
|
station.on("download start", (station, channel, metadata, videoStream, audioStream) => this.onStationStartDownload(station, channel, metadata, videoStream, audioStream));
|
|
station.on("download finish", (station, channel) => this.onStationFinishDownload(station, channel));
|
|
station.on("command result", (station, result) => this.onStationCommandResult(station, result));
|
|
station.on("guard mode", (station, guardMode) => this.onStationGuardMode(station, guardMode));
|
|
station.on("current mode", (station, currentMode) => this.onStationCurrentMode(station, currentMode));
|
|
station.on("rtsp livestream start", (station, channel) => this.onStartStationRTSPLivestream(station, channel));
|
|
station.on("rtsp livestream stop", (station, channel) => this.onStopStationRTSPLivestream(station, channel));
|
|
station.on("rtsp url", (station, channel, value) => this.onStationRtspUrl(station, channel, value));
|
|
station.on("property changed", (station, name, value, ready) => this.onStationPropertyChanged(station, name, value, ready));
|
|
station.on("raw property changed", (station, type, value) => this.onStationRawPropertyChanged(station, type, value));
|
|
station.on("alarm event", (station, alarmEvent) => this.onStationAlarmEvent(station, alarmEvent));
|
|
station.on("runtime state", (station, channel, batteryLevel, temperature) => this.onStationRuntimeState(station, channel, batteryLevel, temperature));
|
|
station.on("charging state", (station, channel, chargeType, batteryLevel) => this.onStationChargingState(station, channel, chargeType, batteryLevel));
|
|
station.on("wifi rssi", (station, channel, rssi) => this.onStationWifiRssi(station, channel, rssi));
|
|
station.on("floodlight manual switch", (station, channel, enabled) => this.onFloodlightManualSwitch(station, channel, enabled));
|
|
station.on("alarm delay event", (station, alarmDelayEvent, alarmDelay) => this.onStationAlarmDelayEvent(station, alarmDelayEvent, alarmDelay));
|
|
station.on("talkback started", (station, channel, talkbackStream) => this.onStationTalkbackStart(station, channel, talkbackStream));
|
|
station.on("talkback stopped", (station, channel) => this.onStationTalkbackStop(station, channel));
|
|
station.on("talkback error", (station, channel, error) => this.onStationTalkbackError(station, channel, error));
|
|
station.on("alarm armed event", (station) => this.onStationAlarmArmedEvent(station));
|
|
station.on("alarm arm delay event", (station, armDelay) => this.onStationArmDelayEvent(station, armDelay));
|
|
station.on("secondary command result", (station, result) => this.onStationSecondaryCommandResult(station, result));
|
|
station.on("device shake alarm", (deviceSN, event) => this.onStationDeviceShakeAlarm(deviceSN, event));
|
|
station.on("device 911 alarm", (deviceSN, event) => this.onStationDevice911Alarm(deviceSN, event));
|
|
station.on("device jammed", (deviceSN) => this.onStationDeviceJammed(deviceSN));
|
|
station.on("device low battery", (deviceSN) => this.onStationDeviceLowBattery(deviceSN));
|
|
station.on("device wrong try-protect alarm", (deviceSN) => this.onStationDeviceWrongTryProtectAlarm(deviceSN));
|
|
station.on("device pin verified", (deviceSN, successfull) => this.onStationDevicePinVerified(deviceSN, successfull));
|
|
station.on("sd info ex", (station, sdStatus, sdCapacity, sdCapacityAvailable) => this.onStationSdInfoEx(station, sdStatus, sdCapacity, sdCapacityAvailable));
|
|
station.on("image download", (station, file, image) => this.onStationImageDownload(station, file, image));
|
|
station.on("database query latest", (station, returnCode, data) => this.onStationDatabaseQueryLatest(station, returnCode, data));
|
|
station.on("database query local", (station, returnCode, data) => this.onStationDatabaseQueryLocal(station, returnCode, data));
|
|
station.on("database count by date", (station, returnCode, data) => this.onStationDatabaseCountByDate(station, returnCode, data));
|
|
station.on("database delete", (station, returnCode, failedIds) => this.onStationDatabaseDelete(station, returnCode, failedIds));
|
|
station.on("sensor status", (station, channel, status) => this.onStationSensorStatus(station, channel, status));
|
|
station.on("garage door status", (station, channel, doorId, status) => this.onStationGarageDoorStatus(station, channel, doorId, status));
|
|
station.on("storage info hb3", (station, channel, storageInfo) => this.onStorageInfoHb3(station, channel, storageInfo));
|
|
this.addStation(station);
|
|
station.initialize();
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("HandleHubs Error", { error: (0, utils_1.getError)(error), stationSN: station.getSerial() });
|
|
}
|
|
return station;
|
|
}));
|
|
}
|
|
}
|
|
Promise.all(promises).then(() => {
|
|
this.loadingEmitter.emit("stations loaded");
|
|
this.stationsLoaded = undefined;
|
|
});
|
|
if (promises.length === 0) {
|
|
this.loadingEmitter.emit("stations loaded");
|
|
this.stationsLoaded = undefined;
|
|
}
|
|
for (const stationSN of stationsSNs) {
|
|
if (!newStationsSNs.includes(stationSN)) {
|
|
this.getStation(stationSN).then((station) => {
|
|
this.removeStation(station);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Error removing station", { error: (0, utils_1.getError)(error), stationSN: stationSN });
|
|
});
|
|
}
|
|
}
|
|
}
|
|
refreshP2PData(station) {
|
|
if (station.isStation() || (device_1.Device.isCamera(station.getDeviceType()) && !device_1.Device.isWiredDoorbell(station.getDeviceType()) || device_1.Device.isSmartSafe(station.getDeviceType()))) {
|
|
station.getCameraInfo();
|
|
}
|
|
if (device_1.Device.isLock(station.getDeviceType())) {
|
|
station.getLockParameters();
|
|
station.getLockStatus();
|
|
}
|
|
if (station.isStation() || (station.hasProperty(types_1.PropertyName.StationSdStatus) && station.getPropertyValue(types_1.PropertyName.StationSdStatus) !== types_2.TFCardStatus.REMOVE)) {
|
|
station.getStorageInfoEx();
|
|
}
|
|
}
|
|
onStationConnect(station) {
|
|
this.emit("station connect", station);
|
|
this.refreshP2PData(station);
|
|
if (this.refreshEufySecurityP2PTimeout[station.getSerial()] !== undefined) {
|
|
clearTimeout(this.refreshEufySecurityP2PTimeout[station.getSerial()]);
|
|
delete this.refreshEufySecurityP2PTimeout[station.getSerial()];
|
|
}
|
|
this.refreshEufySecurityP2PTimeout[station.getSerial()] = setTimeout(() => {
|
|
this.refreshP2PData(station);
|
|
}, this.P2P_REFRESH_INTERVAL_MIN * 60 * 1000);
|
|
}
|
|
onStationConnectionError(station, error) {
|
|
this.emit("station connection error", station, error);
|
|
}
|
|
onStationClose(station) {
|
|
this.emit("station close", station);
|
|
for (const device_sn of this.cameraStationLivestreamTimeout.keys()) {
|
|
this.getDevice(device_sn).then((device) => {
|
|
if (device !== null && device.getStationSerial() === station.getSerial()) {
|
|
clearTimeout(this.cameraStationLivestreamTimeout.get(device_sn));
|
|
this.cameraStationLivestreamTimeout.delete(device_sn);
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station close Error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial() });
|
|
});
|
|
}
|
|
}
|
|
handleDevices(devices) {
|
|
logging_1.rootMainLogger.debug("Got devices", { devices: devices });
|
|
const deviceSNs = Object.keys(this.devices);
|
|
const newDeviceSNs = Object.keys(devices);
|
|
const promises = [];
|
|
const deviceConfig = this.config.deviceConfig;
|
|
for (const device of Object.values(devices)) {
|
|
if (deviceSNs.includes(device.device_sn)) {
|
|
this.updateDevice(device);
|
|
}
|
|
else {
|
|
if (this.devicesLoaded === undefined)
|
|
this.devicesLoaded = (0, utils_1.waitForEvent)(this.loadingEmitter, "devices loaded");
|
|
let new_device;
|
|
if (device_1.Device.isIndoorCamera(device.device_type)) {
|
|
new_device = device_1.IndoorCamera.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isSoloCameras(device.device_type)) {
|
|
new_device = device_1.SoloCamera.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isLockWifiVideo(device.device_type)) {
|
|
new_device = device_1.DoorbellLock.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isBatteryDoorbell(device.device_type)) {
|
|
new_device = device_1.BatteryDoorbellCamera.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isWiredDoorbell(device.device_type) || device_1.Device.isWiredDoorbellDual(device.device_type)) {
|
|
new_device = device_1.WiredDoorbellCamera.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isFloodLight(device.device_type)) {
|
|
new_device = device_1.FloodlightCamera.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isWallLightCam(device.device_type)) {
|
|
new_device = device_1.WallLightCam.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isGarageCamera(device.device_type)) {
|
|
new_device = device_1.GarageCamera.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isSmartDrop(device.device_type)) {
|
|
new_device = device_1.SmartDrop.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isCamera(device.device_type)) {
|
|
new_device = device_1.Camera.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isLock(device.device_type)) {
|
|
new_device = device_1.Lock.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isMotionSensor(device.device_type)) {
|
|
new_device = device_1.MotionSensor.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isEntrySensor(device.device_type)) {
|
|
new_device = device_1.EntrySensor.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isKeyPad(device.device_type)) {
|
|
new_device = device_1.Keypad.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isSmartSafe(device.device_type)) {
|
|
new_device = device_1.SmartSafe.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isSmartTrack(device.device_type)) {
|
|
new_device = device_1.Tracker.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else if (device_1.Device.isLockKeypad(device.device_type)) {
|
|
new_device = device_1.LockKeypad.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
else {
|
|
new_device = device_1.UnknownDevice.getInstance(this.api, device, deviceConfig);
|
|
}
|
|
promises.push(new_device.then((device) => {
|
|
try {
|
|
device.on("property changed", (device, name, value, ready) => this.onDevicePropertyChanged(device, name, value, ready));
|
|
device.on("raw property changed", (device, type, value) => this.onDeviceRawPropertyChanged(device, type, value));
|
|
device.on("crying detected", (device, state) => this.onDeviceCryingDetected(device, state));
|
|
device.on("sound detected", (device, state) => this.onDeviceSoundDetected(device, state));
|
|
device.on("pet detected", (device, state) => this.onDevicePetDetected(device, state));
|
|
device.on("vehicle detected", (device, state) => this.onDeviceVehicleDetected(device, state));
|
|
device.on("motion detected", (device, state) => this.onDeviceMotionDetected(device, state));
|
|
device.on("person detected", (device, state, person) => this.onDevicePersonDetected(device, state, person));
|
|
device.on("rings", (device, state) => this.onDeviceRings(device, state));
|
|
device.on("locked", (device, state) => this.onDeviceLocked(device, state));
|
|
device.on("open", (device, state) => this.onDeviceOpen(device, state));
|
|
device.on("ready", (device) => this.onDeviceReady(device));
|
|
device.on("package delivered", (device, state) => this.onDevicePackageDelivered(device, state));
|
|
device.on("package stranded", (device, state) => this.onDevicePackageStranded(device, state));
|
|
device.on("package taken", (device, state) => this.onDevicePackageTaken(device, state));
|
|
device.on("someone loitering", (device, state) => this.onDeviceSomeoneLoitering(device, state));
|
|
device.on("radar motion detected", (device, state) => this.onDeviceRadarMotionDetected(device, state));
|
|
device.on("911 alarm", (device, state, detail) => this.onDevice911Alarm(device, state, detail));
|
|
device.on("shake alarm", (device, state, detail) => this.onDeviceShakeAlarm(device, state, detail));
|
|
device.on("wrong try-protect alarm", (device, state) => this.onDeviceWrongTryProtectAlarm(device, state));
|
|
device.on("long time not close", (device, state) => this.onDeviceLongTimeNotClose(device, state));
|
|
device.on("low battery", (device, state) => this.onDeviceLowBattery(device, state));
|
|
device.on("jammed", (device, state) => this.onDeviceJammed(device, state));
|
|
device.on("stranger person detected", (device, state) => this.onDeviceStrangerPersonDetected(device, state));
|
|
device.on("dog detected", (device, state) => this.onDeviceDogDetected(device, state));
|
|
device.on("dog lick detected", (device, state) => this.onDeviceDogLickDetected(device, state));
|
|
device.on("dog poop detected", (device, state) => this.onDeviceDogPoopDetected(device, state));
|
|
device.on("tampering", (device, state) => this.onDeviceTampering(device, state));
|
|
device.on("low temperature", (device, state) => this.onDeviceLowTemperature(device, state));
|
|
device.on("high temperature", (device, state) => this.onDeviceHighTemperature(device, state));
|
|
device.on("pin incorrect", (device, state) => this.onDevicePinIncorrect(device, state));
|
|
device.on("lid stuck", (device, state) => this.onDeviceLidStuck(device, state));
|
|
device.on("battery fully charged", (device, state) => this.onDeviceBatteryFullyCharged(device, state));
|
|
this.addDevice(device);
|
|
device.initialize();
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("HandleDevices Error", { error: (0, utils_1.getError)(error), deviceSN: device.getSerial() });
|
|
}
|
|
return device;
|
|
}));
|
|
}
|
|
}
|
|
Promise.all(promises).then((devices) => {
|
|
devices.forEach((device) => {
|
|
this.getStation(device.getStationSerial()).then((station) => {
|
|
if (!station.isConnected() && station.isP2PConnectableDevice()) {
|
|
station.setConnectionType(this.config.p2pConnectionSetup);
|
|
logging_1.rootMainLogger.debug(`Initiate first station connection to get data over p2p`, { stationSN: station.getSerial() });
|
|
station.connect();
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Error trying to connect to station afte device loaded", { error: (0, utils_1.getError)(error), deviceSN: device.getSerial() });
|
|
});
|
|
});
|
|
this.loadingEmitter.emit("devices loaded");
|
|
this.devicesLoaded = undefined;
|
|
});
|
|
if (promises.length === 0) {
|
|
this.loadingEmitter.emit("devices loaded");
|
|
this.devicesLoaded = undefined;
|
|
}
|
|
for (const deviceSN of deviceSNs) {
|
|
if (!newDeviceSNs.includes(deviceSN)) {
|
|
this.getDevice(deviceSN).then((device) => {
|
|
this.removeDevice(device);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Error removing device", { error: (0, utils_1.getError)(error), deviceSN: deviceSN });
|
|
});
|
|
}
|
|
}
|
|
}
|
|
async refreshCloudData() {
|
|
if (this.config.acceptInvitations) {
|
|
await this.processInvitations().catch(err => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Error in processing invitations", { error: (0, utils_1.getError)(error) });
|
|
});
|
|
}
|
|
await this.api.refreshAllData().catch(err => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Error during API data refreshing", { error: (0, utils_1.getError)(error) });
|
|
});
|
|
if (this.refreshEufySecurityCloudTimeout !== undefined)
|
|
clearTimeout(this.refreshEufySecurityCloudTimeout);
|
|
if (this.config.pollingIntervalMinutes > 0)
|
|
this.refreshEufySecurityCloudTimeout = setTimeout(() => { this.refreshCloudData(); }, this.config.pollingIntervalMinutes * 60 * 1000);
|
|
else
|
|
logging_1.rootMainLogger.info(`Automatic retrieval of data from the cloud has been deactivated (config pollingIntervalMinutes: ${this.config.pollingIntervalMinutes})`);
|
|
}
|
|
close() {
|
|
for (const device_sn of this.cameraStationLivestreamTimeout.keys()) {
|
|
this.stopStationLivestream(device_sn);
|
|
}
|
|
if (this.refreshEufySecurityCloudTimeout !== undefined)
|
|
clearTimeout(this.refreshEufySecurityCloudTimeout);
|
|
Object.keys(this.refreshEufySecurityP2PTimeout).forEach(station_sn => {
|
|
clearTimeout(this.refreshEufySecurityP2PTimeout[station_sn]);
|
|
delete this.refreshEufySecurityP2PTimeout[station_sn];
|
|
});
|
|
Object.keys(this.deviceSnoozeTimeout).forEach(device_sn => {
|
|
clearTimeout(this.deviceSnoozeTimeout[device_sn]);
|
|
delete this.deviceSnoozeTimeout[device_sn];
|
|
});
|
|
this.savePushPersistentIds();
|
|
this.pushService.close();
|
|
this.mqttService.close();
|
|
Object.values(this.stations).forEach(station => {
|
|
station.close();
|
|
});
|
|
Object.values(this.devices).forEach(device => {
|
|
device.destroy();
|
|
});
|
|
if (this.connected)
|
|
this.emit("close");
|
|
this.connected = false;
|
|
}
|
|
setCameraMaxLivestreamDuration(seconds) {
|
|
this.cameraMaxLivestreamSeconds = seconds;
|
|
}
|
|
getCameraMaxLivestreamDuration() {
|
|
return this.cameraMaxLivestreamSeconds;
|
|
}
|
|
async registerPushNotifications(credentials, persistentIds) {
|
|
if (credentials)
|
|
this.pushService.setCredentials(credentials);
|
|
if (persistentIds)
|
|
this.pushService.setPersistentIds(persistentIds);
|
|
this.pushService.open();
|
|
}
|
|
async connect(options) {
|
|
await this.api.login(options)
|
|
.then(async () => {
|
|
if (options?.verifyCode) {
|
|
let trusted = false;
|
|
const trusted_devices = await this.api.listTrustDevice();
|
|
trusted_devices.forEach(trusted_device => {
|
|
if (trusted_device.is_current_device === 1) {
|
|
trusted = true;
|
|
}
|
|
});
|
|
if (!trusted)
|
|
return await this.api.addTrustDevice(options?.verifyCode);
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Connect Error", { error: (0, utils_1.getError)(error), options: options });
|
|
});
|
|
}
|
|
getPushPersistentIds() {
|
|
return this.pushService.getPersistentIds();
|
|
}
|
|
updateDeviceProperties(deviceSN, values) {
|
|
this.getDevice(deviceSN).then((device) => {
|
|
device.updateRawProperties(values);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Update device properties error", { error: (0, utils_1.getError)(error), deviceSN: deviceSN, values: values });
|
|
});
|
|
}
|
|
async onAPIClose() {
|
|
if (this.refreshEufySecurityCloudTimeout !== undefined)
|
|
clearTimeout(this.refreshEufySecurityCloudTimeout);
|
|
this.connected = false;
|
|
this.emit("close");
|
|
if (this.retries < 3) {
|
|
this.retries++;
|
|
await this.connect();
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.error(`Tried to re-authenticate to Eufy cloud, but failed in the process. Manual intervention is required!`);
|
|
}
|
|
}
|
|
async onAPIConnect() {
|
|
this.connected = true;
|
|
this.retries = 0;
|
|
this.saveCloudToken();
|
|
await this.refreshCloudData();
|
|
this.emit("connect");
|
|
this.registerPushNotifications(this.persistentData.push_credentials, this.persistentData.push_persistentIds);
|
|
const loginData = this.api.getPersistentData();
|
|
if (loginData) {
|
|
this.mqttService.connect(loginData.user_id, this.persistentData.openudid, this.api.getAPIBase(), loginData.email);
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.warn("No login data recevied to initialize MQTT connection...");
|
|
}
|
|
}
|
|
onAPIConnectionError(error) {
|
|
this.emit("connection error", error);
|
|
}
|
|
async startStationLivestream(deviceSN) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
if (!device.hasCommand(types_1.CommandName.DeviceStartLivestream))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStartLivestream } });
|
|
const camera = device;
|
|
if (!station.isLiveStreaming(camera)) {
|
|
station.startLivestream(camera);
|
|
if (this.cameraMaxLivestreamSeconds > 0) {
|
|
this.cameraStationLivestreamTimeout.set(deviceSN, setTimeout(() => {
|
|
logging_1.rootMainLogger.info(`Stopping the station stream for the device ${deviceSN}, because we have reached the configured maximum stream timeout (${this.cameraMaxLivestreamSeconds} seconds)`);
|
|
this.stopStationLivestream(deviceSN);
|
|
}, this.cameraMaxLivestreamSeconds * 1000));
|
|
}
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.warn(`The station stream for the device ${deviceSN} cannot be started, because it is already streaming!`);
|
|
}
|
|
}
|
|
async stopStationLivestream(deviceSN) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
if (!device.hasCommand(types_1.CommandName.DeviceStopLivestream))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStopLivestream } });
|
|
if (station.isConnected() && station.isLiveStreaming(device)) {
|
|
station.stopLivestream(device);
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.warn(`The station stream for the device ${deviceSN} cannot be stopped, because it isn't streaming!`);
|
|
}
|
|
const timeout = this.cameraStationLivestreamTimeout.get(deviceSN);
|
|
if (timeout) {
|
|
clearTimeout(timeout);
|
|
this.cameraStationLivestreamTimeout.delete(deviceSN);
|
|
}
|
|
}
|
|
writePersistentData() {
|
|
this.persistentData.login_hash = (0, utils_1.md5)(`${this.config.username}:${this.config.password}`);
|
|
if (this.api.isConnected()) {
|
|
this.persistentData.httpApi = this.api?.getPersistentData();
|
|
this.persistentData.country = this.api?.getCountry();
|
|
}
|
|
try {
|
|
if (this.config.persistentData) {
|
|
this.emit("persistent data", JSON.stringify(this.persistentData));
|
|
}
|
|
else {
|
|
fse.writeFileSync(this.persistentFile, JSON.stringify(this.persistentData));
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("WritePersistentData Error", { error: (0, utils_1.getError)(error) });
|
|
}
|
|
}
|
|
saveCloudToken() {
|
|
const token = this.api.getToken();
|
|
const token_expiration = this.api.getTokenExpiration();
|
|
if (!!token && !!token_expiration) {
|
|
logging_1.rootMainLogger.debug("Save cloud token and token expiration", { token: token, tokenExpiration: token_expiration });
|
|
this.persistentData.cloud_token = token;
|
|
this.persistentData.cloud_token_expiration = token_expiration.getTime();
|
|
this.writePersistentData();
|
|
}
|
|
}
|
|
savePushCredentials(credentials) {
|
|
this.persistentData.push_credentials = credentials;
|
|
this.writePersistentData();
|
|
}
|
|
savePushPersistentIds() {
|
|
this.persistentData.push_persistentIds = this.getPushPersistentIds();
|
|
this.writePersistentData();
|
|
}
|
|
getVersion() {
|
|
return _1.libVersion;
|
|
}
|
|
isPushConnected() {
|
|
return this.pushService.isConnected();
|
|
}
|
|
isMQTTConnected() {
|
|
return this.mqttService.isConnected();
|
|
}
|
|
isConnected() {
|
|
return this.connected;
|
|
}
|
|
async processInvitations() {
|
|
let refreshCloud = false;
|
|
const invites = await this.api.getInvites().catch(err => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Error getting invites from cloud", { error: (0, utils_1.getError)(error) });
|
|
return error;
|
|
});
|
|
if (Object.keys(invites).length > 0) {
|
|
const confirmInvites = [];
|
|
for (const invite of Object.values(invites)) {
|
|
const devices = [];
|
|
invite.devices.forEach(device => {
|
|
devices.push(device.device_sn);
|
|
});
|
|
if (devices.length > 0) {
|
|
confirmInvites.push({
|
|
invite_id: invite.invite_id,
|
|
station_sn: invite.station_sn,
|
|
device_sns: devices
|
|
});
|
|
}
|
|
}
|
|
if (confirmInvites.length > 0) {
|
|
const result = await this.api.confirmInvites(confirmInvites).catch(err => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Error in confirmation of invitations", { error: (0, utils_1.getError)(error), confirmInvites: confirmInvites });
|
|
return error;
|
|
});
|
|
if (result) {
|
|
logging_1.rootMainLogger.info(`Accepted received invitations`, confirmInvites);
|
|
refreshCloud = true;
|
|
}
|
|
}
|
|
}
|
|
const houseInvites = await this.api.getHouseInviteList().catch(err => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Error getting house invites from cloud", { error: (0, utils_1.getError)(error) });
|
|
return error;
|
|
});
|
|
if (Object.keys(houseInvites).length > 0) {
|
|
for (const invite of Object.values(houseInvites)) {
|
|
const result = await this.api.confirmHouseInvite(invite.house_id, invite.id).catch(err => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Error in confirmation of house invitations", { error: (0, utils_1.getError)(error) });
|
|
return error;
|
|
});
|
|
if (result) {
|
|
logging_1.rootMainLogger.info(`Accepted received house invitation from ${invite.action_user_email}`, { invite: invite });
|
|
refreshCloud = true;
|
|
}
|
|
}
|
|
}
|
|
if (refreshCloud)
|
|
this.refreshCloudData();
|
|
}
|
|
onPushMessage(message) {
|
|
this.emit("push message", message);
|
|
try {
|
|
logging_1.rootMainLogger.debug("Received push message", { message: message });
|
|
try {
|
|
if ((message.type === types_3.ServerPushEvent.INVITE_DEVICE || message.type === types_3.ServerPushEvent.HOUSE_INVITE) && this.config.acceptInvitations) {
|
|
if (this.isConnected())
|
|
this.processInvitations();
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Error processing server push notification for device invitation`, { error: (0, utils_1.getError)(error), message: message });
|
|
}
|
|
try {
|
|
if (message.type === types_3.ServerPushEvent.REMOVE_DEVICE || message.type === types_3.ServerPushEvent.REMOVE_HOMEBASE || message.type === types_3.ServerPushEvent.HOUSE_REMOVE) {
|
|
if (this.isConnected())
|
|
this.refreshCloudData();
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Error processing server push notification for device/station/house removal`, { error: (0, utils_1.getError)(error), message: message });
|
|
}
|
|
this.getStations().then((stations) => {
|
|
stations.forEach(station => {
|
|
try {
|
|
station.processPushNotification(message);
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Error processing push notification for station`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), message: message });
|
|
}
|
|
});
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Process push notification for stations", { error: (0, utils_1.getError)(error), message: message });
|
|
});
|
|
this.getDevices().then((devices) => {
|
|
devices.forEach(device => {
|
|
this.getStation(device.getStationSerial()).then((station) => {
|
|
try {
|
|
device.processPushNotification(station, message, this.config.eventDurationSeconds);
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Error processing push notification for device`, { error: (0, utils_1.getError)(error), deviceSN: device.getSerial(), message: message });
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Process push notification for devices loading station", { error: (0, utils_1.getError)(error), message: message });
|
|
});
|
|
});
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Process push notification for devices", { error: (0, utils_1.getError)(error), message: message });
|
|
});
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("OnPushMessage Generic Error", { error: (0, utils_1.getError)(error), message: message });
|
|
}
|
|
}
|
|
async startStationDownload(deviceSN, path, cipherID) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
if (!device.hasCommand(types_1.CommandName.DeviceStartDownload))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStartDownload, path: path, cipherID: cipherID } });
|
|
if (!station.isDownloading(device)) {
|
|
await station.startDownload(device, path, cipherID);
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.warn(`The station is already downloading a video for the device ${deviceSN}!`);
|
|
}
|
|
}
|
|
async cancelStationDownload(deviceSN) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
if (!device.hasCommand(types_1.CommandName.DeviceCancelDownload))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceCancelDownload } });
|
|
if (station.isConnected() && station.isDownloading(device)) {
|
|
station.cancelDownload(device);
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.warn(`The station isn't downloading a video for the device ${deviceSN}!`);
|
|
}
|
|
}
|
|
getConfig() {
|
|
return this.config;
|
|
}
|
|
async setDeviceProperty(deviceSN, name, value) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
const metadata = device.getPropertyMetadata(name);
|
|
value = (0, utils_1.parseValue)(metadata, value);
|
|
switch (name) {
|
|
case types_1.PropertyName.DeviceEnabled:
|
|
station.enableDevice(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceStatusLed:
|
|
station.setStatusLed(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceAutoNightvision:
|
|
station.setAutoNightVision(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetection:
|
|
station.setMotionDetection(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceSoundDetection:
|
|
station.setSoundDetection(device, value);
|
|
break;
|
|
case types_1.PropertyName.DevicePetDetection:
|
|
station.setPetDetection(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRTSPStream:
|
|
station.setRTSPStream(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceAntitheftDetection:
|
|
station.setAntiTheftDetection(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLocked:
|
|
station.lockDevice(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceWatermark:
|
|
station.setWatermark(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLight:
|
|
station.switchLight(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsEnable:
|
|
station.setFloodlightLightSettingsEnable(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsBrightnessManual:
|
|
station.setFloodlightLightSettingsBrightnessManual(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsBrightnessMotion:
|
|
station.setFloodlightLightSettingsBrightnessMotion(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsBrightnessSchedule:
|
|
station.setFloodlightLightSettingsBrightnessSchedule(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsMotionTriggered:
|
|
station.setFloodlightLightSettingsMotionTriggered(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsMotionTriggeredDistance:
|
|
station.setFloodlightLightSettingsMotionTriggeredDistance(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsMotionTriggeredTimer:
|
|
station.setFloodlightLightSettingsMotionTriggeredTimer(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMicrophone:
|
|
station.setMicMute(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceSpeaker:
|
|
station.enableSpeaker(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceSpeakerVolume:
|
|
station.setSpeakerVolume(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceAudioRecording:
|
|
station.setAudioRecording(device, value);
|
|
break;
|
|
case types_1.PropertyName.DevicePowerSource:
|
|
station.setPowerSource(device, value);
|
|
break;
|
|
case types_1.PropertyName.DevicePowerWorkingMode:
|
|
station.setPowerWorkingMode(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRecordingEndClipMotionStops:
|
|
station.setRecordingEndClipMotionStops(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRecordingClipLength:
|
|
station.setRecordingClipLength(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRecordingRetriggerInterval:
|
|
station.setRecordingRetriggerInterval(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceVideoStreamingQuality:
|
|
station.setVideoStreamingQuality(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceVideoRecordingQuality:
|
|
station.setVideoRecordingQuality(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivity:
|
|
station.setMotionDetectionSensitivity(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionTracking:
|
|
station.setMotionTracking(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionType:
|
|
station.setMotionDetectionType(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionZone:
|
|
station.setMotionZone(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceVideoWDR:
|
|
station.setWDR(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRingtoneVolume:
|
|
station.setRingtoneVolume(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceChimeIndoor:
|
|
station.enableIndoorChime(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceChimeHomebase:
|
|
station.enableHomebaseChime(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceChimeHomebaseRingtoneVolume:
|
|
station.setHomebaseChimeRingtoneVolume(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceChimeHomebaseRingtoneType:
|
|
station.setHomebaseChimeRingtoneType(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationType:
|
|
station.setNotificationType(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationPerson:
|
|
if (device.isIndoorPanAndTiltCameraS350()) {
|
|
station.setNotificationIndoor(device, types_1.IndoorS350NotificationTypes.HUMAN, value);
|
|
}
|
|
else if (device.isFloodLightT8425()) {
|
|
station.setNotificationFloodlightT8425(device, types_1.FloodlightT8425NotificationTypes.HUMAN, value);
|
|
}
|
|
else {
|
|
station.setNotificationPerson(device, value);
|
|
}
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationPet:
|
|
if (device.isIndoorPanAndTiltCameraS350()) {
|
|
station.setNotificationIndoor(device, types_1.IndoorS350NotificationTypes.PET, value);
|
|
}
|
|
else if (device.isFloodLightT8425()) {
|
|
station.setNotificationFloodlightT8425(device, types_1.FloodlightT8425NotificationTypes.PET, value);
|
|
}
|
|
else {
|
|
station.setNotificationPet(device, value);
|
|
}
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationAllOtherMotion:
|
|
if (device.isIndoorPanAndTiltCameraS350()) {
|
|
station.setNotificationIndoor(device, types_1.IndoorS350NotificationTypes.ALL_OTHER_MOTION, value);
|
|
}
|
|
else if (device.isFloodLightT8425()) {
|
|
station.setNotificationFloodlightT8425(device, types_1.FloodlightT8425NotificationTypes.ALL_OTHER_MOTION, value);
|
|
}
|
|
else {
|
|
station.setNotificationAllOtherMotion(device, value);
|
|
}
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationAllSound:
|
|
if (device.isIndoorPanAndTiltCameraS350()) {
|
|
station.setNotificationIndoor(device, types_1.IndoorS350NotificationTypes.ALL_SOUND, value);
|
|
}
|
|
else {
|
|
station.setNotificationAllSound(device, value);
|
|
}
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationCrying:
|
|
if (device.isIndoorPanAndTiltCameraS350()) {
|
|
station.setNotificationIndoor(device, types_1.IndoorS350NotificationTypes.CRYING, value);
|
|
}
|
|
else {
|
|
station.setNotificationCrying(device, value);
|
|
}
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationVehicle:
|
|
if (device.isFloodLightT8425()) {
|
|
station.setNotificationFloodlightT8425(device, types_1.FloodlightT8425NotificationTypes.VEHICLE, value);
|
|
}
|
|
else {
|
|
throw new error_2.InvalidPropertyError("Station has no writable property", { context: { station: station.getSerial(), propertyName: name, propertyValue: value } });
|
|
}
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationMotion:
|
|
station.setNotificationMotion(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationRing:
|
|
station.setNotificationRing(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceChirpVolume:
|
|
station.setChirpVolume(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceChirpTone:
|
|
station.setChirpTone(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceVideoHDR:
|
|
station.setHDR(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceVideoDistortionCorrection:
|
|
station.setDistortionCorrection(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceVideoRingRecord:
|
|
station.setRingRecord(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRotationSpeed:
|
|
station.setPanAndTiltRotationSpeed(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNightvision:
|
|
station.setNightVision(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionRange:
|
|
station.setMotionDetectionRange(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionRangeStandardSensitivity:
|
|
station.setMotionDetectionRangeStandardSensitivity(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionRangeAdvancedLeftSensitivity:
|
|
station.setMotionDetectionRangeAdvancedLeftSensitivity(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionRangeAdvancedMiddleSensitivity:
|
|
station.setMotionDetectionRangeAdvancedMiddleSensitivity(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionRangeAdvancedRightSensitivity:
|
|
station.setMotionDetectionRangeAdvancedRightSensitivity(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionTestMode:
|
|
station.setMotionDetectionTestMode(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionTrackingSensitivity:
|
|
station.setMotionTrackingSensitivity(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionAutoCruise:
|
|
station.setMotionAutoCruise(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionOutOfViewDetection:
|
|
station.setMotionOutOfViewDetection(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsColorTemperatureManual:
|
|
station.setLightSettingsColorTemperatureManual(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsColorTemperatureMotion:
|
|
station.setLightSettingsColorTemperatureMotion(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsColorTemperatureSchedule:
|
|
station.setLightSettingsColorTemperatureSchedule(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsMotionActivationMode:
|
|
station.setLightSettingsMotionActivationMode(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceVideoNightvisionImageAdjustment:
|
|
station.setVideoNightvisionImageAdjustment(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceVideoColorNightvision:
|
|
station.setVideoColorNightvision(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceAutoCalibration:
|
|
station.setAutoCalibration(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceAutoLock:
|
|
station.setAutoLock(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceAutoLockSchedule:
|
|
station.setAutoLockSchedule(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceAutoLockScheduleStartTime:
|
|
station.setAutoLockScheduleStartTime(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceAutoLockScheduleEndTime:
|
|
station.setAutoLockScheduleEndTime(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceAutoLockTimer:
|
|
station.setAutoLockTimer(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceOneTouchLocking:
|
|
station.setOneTouchLocking(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceSound:
|
|
station.setSound(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNotification:
|
|
station.setNotification(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationLocked:
|
|
station.setNotificationLocked(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationUnlocked:
|
|
station.setNotificationUnlocked(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceScramblePasscode:
|
|
station.setScramblePasscode(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceWrongTryProtection:
|
|
station.setWrongTryProtection(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceWrongTryAttempts:
|
|
station.setWrongTryAttempts(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceWrongTryLockdownTime:
|
|
station.setWrongTryLockdownTime(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLoiteringDetection:
|
|
station.setLoiteringDetection(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLoiteringDetectionRange:
|
|
station.setLoiteringDetectionRange(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLoiteringDetectionLength:
|
|
station.setLoiteringDetectionLength(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLoiteringCustomResponseAutoVoiceResponse:
|
|
station.setLoiteringCustomResponseAutoVoiceResponse(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLoiteringCustomResponseHomeBaseNotification:
|
|
station.setLoiteringCustomResponseHomeBaseNotification(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLoiteringCustomResponsePhoneNotification:
|
|
station.setLoiteringCustomResponsePhoneNotification(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLoiteringCustomResponseAutoVoiceResponseVoice:
|
|
station.setLoiteringCustomResponseAutoVoiceResponseVoice(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLoiteringCustomResponseTimeFrom:
|
|
station.setLoiteringCustomResponseTimeFrom(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLoiteringCustomResponseTimeTo:
|
|
station.setLoiteringCustomResponseTimeTo(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivityMode:
|
|
station.setMotionDetectionSensitivityMode(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivityStandard:
|
|
station.setMotionDetectionSensitivityStandard(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivityAdvancedA:
|
|
station.setMotionDetectionSensitivityAdvancedA(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivityAdvancedB:
|
|
station.setMotionDetectionSensitivityAdvancedB(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivityAdvancedC:
|
|
station.setMotionDetectionSensitivityAdvancedC(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivityAdvancedD:
|
|
station.setMotionDetectionSensitivityAdvancedD(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivityAdvancedE:
|
|
station.setMotionDetectionSensitivityAdvancedE(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivityAdvancedF:
|
|
station.setMotionDetectionSensitivityAdvancedF(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivityAdvancedG:
|
|
station.setMotionDetectionSensitivityAdvancedG(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionSensitivityAdvancedH:
|
|
station.setMotionDetectionSensitivityAdvancedH(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDeliveryGuard:
|
|
station.setDeliveryGuard(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDeliveryGuardPackageGuarding:
|
|
station.setDeliveryGuardPackageGuarding(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDeliveryGuardPackageGuardingVoiceResponseVoice:
|
|
station.setDeliveryGuardPackageGuardingVoiceResponseVoice(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDeliveryGuardPackageGuardingActivatedTimeFrom:
|
|
station.setDeliveryGuardPackageGuardingActivatedTimeFrom(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDeliveryGuardPackageGuardingActivatedTimeTo:
|
|
station.setDeliveryGuardPackageGuardingActivatedTimeTo(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDeliveryGuardUncollectedPackageAlert:
|
|
station.setDeliveryGuardUncollectedPackageAlert(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDeliveryGuardPackageLiveCheckAssistance:
|
|
station.setDeliveryGuardPackageLiveCheckAssistance(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDualCamWatchViewMode:
|
|
station.setDualCamWatchViewMode(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRingAutoResponse:
|
|
station.setRingAutoResponse(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRingAutoResponseVoiceResponse:
|
|
station.setRingAutoResponseVoiceResponse(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRingAutoResponseVoiceResponseVoice:
|
|
station.setRingAutoResponseVoiceResponseVoice(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRingAutoResponseTimeFrom:
|
|
station.setRingAutoResponseTimeFrom(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceRingAutoResponseTimeTo:
|
|
station.setRingAutoResponseTimeTo(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationRadarDetector:
|
|
station.setNotificationRadarDetector(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceSoundDetectionSensitivity:
|
|
station.setSoundDetectionSensitivity(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceContinuousRecording:
|
|
station.setContinuousRecording(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceContinuousRecordingType:
|
|
station.setContinuousRecordingType(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDefaultAngle:
|
|
station.enableDefaultAngle(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDefaultAngleIdleTime:
|
|
station.setDefaultAngleIdleTime(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNotificationIntervalTime:
|
|
station.setNotificationIntervalTime(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceSoundDetectionRoundLook:
|
|
station.setSoundDetectionRoundLook(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDeliveryGuardUncollectedPackageAlertTimeToCheck:
|
|
station.setDeliveryGuardUncollectedPackageAlertTimeToCheck(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLeftOpenAlarm:
|
|
case types_1.PropertyName.DeviceLeftOpenAlarmDuration:
|
|
case types_1.PropertyName.DeviceDualUnlock:
|
|
case types_1.PropertyName.DevicePowerSave:
|
|
case types_1.PropertyName.DeviceInteriorBrightness:
|
|
case types_1.PropertyName.DeviceInteriorBrightnessDuration:
|
|
case types_1.PropertyName.DeviceTamperAlarm:
|
|
case types_1.PropertyName.DeviceRemoteUnlock:
|
|
case types_1.PropertyName.DeviceRemoteUnlockMasterPIN:
|
|
case types_1.PropertyName.DeviceAlarmVolume:
|
|
case types_1.PropertyName.DevicePromptVolume:
|
|
case types_1.PropertyName.DeviceNotificationUnlockByKey:
|
|
case types_1.PropertyName.DeviceNotificationUnlockByPIN:
|
|
case types_1.PropertyName.DeviceNotificationUnlockByFingerprint:
|
|
case types_1.PropertyName.DeviceNotificationUnlockByApp:
|
|
case types_1.PropertyName.DeviceNotificationDualUnlock:
|
|
case types_1.PropertyName.DeviceNotificationDualLock:
|
|
case types_1.PropertyName.DeviceNotificationWrongTryProtect:
|
|
case types_1.PropertyName.DeviceNotificationJammed:
|
|
station.setSmartSafeParams(device, name, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceVideoTypeStoreToNAS:
|
|
station.setVideoTypeStoreToNAS(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionTypeHumanRecognition:
|
|
station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.HUMAN_RECOGNITION, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionTypeHuman:
|
|
if (device.isWallLightCam()) {
|
|
station.setMotionDetectionTypeHuman(device, value);
|
|
}
|
|
else if (device.isOutdoorPanAndTiltCamera()) {
|
|
station.setMotionDetectionTypeHB3(device, types_1.T8170DetectionTypes.HUMAN_DETECTION, value);
|
|
}
|
|
else if (device.isSoloCameras()) {
|
|
station.setMotionDetectionTypeHB3(device, types_1.SoloCameraDetectionTypes.HUMAN_DETECTION, value);
|
|
}
|
|
else if (device.isIndoorPanAndTiltCameraS350()) {
|
|
station.setMotionDetectionTypeHB3(device, types_1.IndoorS350DetectionTypes.HUMAN_DETECTION, value);
|
|
}
|
|
else {
|
|
station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.HUMAN_DETECTION, value);
|
|
}
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionTypePet:
|
|
if (device.isIndoorPanAndTiltCameraS350()) {
|
|
station.setMotionDetectionTypeHB3(device, types_1.IndoorS350DetectionTypes.PET_DETECTION, value);
|
|
}
|
|
else {
|
|
station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.PET_DETECTION, value);
|
|
}
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionTypeVehicle:
|
|
if (device.isOutdoorPanAndTiltCamera()) {
|
|
station.setMotionDetectionTypeHB3(device, types_1.T8170DetectionTypes.VEHICLE_DETECTION, value);
|
|
}
|
|
else {
|
|
station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.VEHICLE_DETECTION, value);
|
|
}
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionDetectionTypeAllOtherMotions:
|
|
if (device.isWallLightCam()) {
|
|
station.setMotionDetectionTypeAllOtherMotions(device, value);
|
|
}
|
|
else if (device.isOutdoorPanAndTiltCamera()) {
|
|
station.setMotionDetectionTypeHB3(device, types_1.T8170DetectionTypes.ALL_OTHER_MOTION, value);
|
|
}
|
|
else if (device.isSoloCameras()) {
|
|
station.setMotionDetectionTypeHB3(device, types_1.SoloCameraDetectionTypes.ALL_OTHER_MOTION, value);
|
|
}
|
|
else if (device.isIndoorPanAndTiltCameraS350()) {
|
|
station.setMotionDetectionTypeHB3(device, types_1.IndoorS350DetectionTypes.ALL_OTHER_MOTION, value);
|
|
}
|
|
else {
|
|
station.setMotionDetectionTypeHB3(device, types_1.HB3DetectionTypes.ALL_OTHER_MOTION, value);
|
|
}
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsManualLightingActiveMode:
|
|
station.setLightSettingsManualLightingActiveMode(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsManualDailyLighting:
|
|
station.setLightSettingsManualDailyLighting(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsManualColoredLighting:
|
|
station.setLightSettingsManualColoredLighting(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsManualDynamicLighting:
|
|
station.setLightSettingsManualDynamicLighting(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsMotionLightingActiveMode:
|
|
station.setLightSettingsMotionLightingActiveMode(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsMotionDailyLighting:
|
|
station.setLightSettingsMotionDailyLighting(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsMotionColoredLighting:
|
|
station.setLightSettingsMotionColoredLighting(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsMotionDynamicLighting:
|
|
station.setLightSettingsMotionDynamicLighting(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsScheduleLightingActiveMode:
|
|
station.setLightSettingsScheduleLightingActiveMode(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsScheduleDailyLighting:
|
|
station.setLightSettingsScheduleDailyLighting(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsScheduleColoredLighting:
|
|
station.setLightSettingsScheduleColoredLighting(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsScheduleDynamicLighting:
|
|
station.setLightSettingsScheduleDynamicLighting(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsColoredLightingColors:
|
|
station.setLightSettingsColoredLightingColors(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLightSettingsDynamicLightingThemes:
|
|
station.setLightSettingsDynamicLightingThemes(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDoorControlWarning:
|
|
station.setDoorControlWarning(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceDoor1Open:
|
|
station.openDoor(device, value, 1);
|
|
break;
|
|
case types_1.PropertyName.DeviceDoor2Open:
|
|
station.openDoor(device, value, 2);
|
|
break;
|
|
case types_1.PropertyName.DeviceLeftBehindAlarm: {
|
|
const tracker = device;
|
|
const result = await tracker.setLeftBehindAlarm(value);
|
|
if (result) {
|
|
device.updateProperty(name, value);
|
|
}
|
|
break;
|
|
}
|
|
case types_1.PropertyName.DeviceFindPhone: {
|
|
const tracker = device;
|
|
const result = await tracker.setFindPhone(value);
|
|
if (result) {
|
|
device.updateProperty(name, value);
|
|
}
|
|
break;
|
|
}
|
|
case types_1.PropertyName.DeviceTrackerType: {
|
|
const tracker = device;
|
|
const result = await tracker.setTrackerType(value);
|
|
if (result) {
|
|
device.updateProperty(name, value);
|
|
}
|
|
break;
|
|
}
|
|
case types_1.PropertyName.DeviceImageMirrored:
|
|
station.setMirrorMode(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceFlickerAdjustment:
|
|
station.setFlickerAdjustment(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceSoundDetectionType:
|
|
station.setSoundDetectionType(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLeavingDetection:
|
|
station.setLeavingDetection(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLeavingReactionNotification:
|
|
station.setLeavingReactionNotification(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLeavingReactionStartTime:
|
|
station.setLeavingReactionStartTime(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceLeavingReactionEndTime:
|
|
station.setLeavingReactionEndTime(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceBeepVolume:
|
|
station.setBeepVolume(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNightvisionOptimization:
|
|
station.setNightvisionOptimization(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceNightvisionOptimizationSide:
|
|
station.setNightvisionOptimizationSide(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceOpenMethod:
|
|
station.setOpenMethod(device, value);
|
|
break;
|
|
case types_1.PropertyName.DeviceMotionActivatedPrompt:
|
|
station.setMotionActivatedPrompt(device, value);
|
|
break;
|
|
default:
|
|
if (!Object.values(types_1.PropertyName).includes(name))
|
|
throw new error_1.ReadOnlyPropertyError("Property is read only", { context: { device: deviceSN, propertyName: name, propertyValue: value } });
|
|
throw new error_2.InvalidPropertyError("Device has no writable property", { context: { device: deviceSN, propertyName: name, propertyValue: value } });
|
|
}
|
|
}
|
|
async setStationProperty(stationSN, name, value) {
|
|
const station = await this.getStation(stationSN);
|
|
const metadata = station.getPropertyMetadata(name);
|
|
value = (0, utils_1.parseValue)(metadata, value);
|
|
switch (name) {
|
|
case types_1.PropertyName.StationGuardMode:
|
|
station.setGuardMode(value);
|
|
break;
|
|
case types_1.PropertyName.StationAlarmTone:
|
|
station.setStationAlarmTone(value);
|
|
break;
|
|
case types_1.PropertyName.StationAlarmVolume:
|
|
station.setStationAlarmRingtoneVolume(value);
|
|
break;
|
|
case types_1.PropertyName.StationPromptVolume:
|
|
station.setStationPromptVolume(value);
|
|
break;
|
|
case types_1.PropertyName.StationNotificationSwitchModeApp:
|
|
station.setStationNotificationSwitchMode(types_1.NotificationSwitchMode.APP, value);
|
|
break;
|
|
case types_1.PropertyName.StationNotificationSwitchModeGeofence:
|
|
station.setStationNotificationSwitchMode(types_1.NotificationSwitchMode.GEOFENCE, value);
|
|
break;
|
|
case types_1.PropertyName.StationNotificationSwitchModeSchedule:
|
|
station.setStationNotificationSwitchMode(types_1.NotificationSwitchMode.SCHEDULE, value);
|
|
break;
|
|
case types_1.PropertyName.StationNotificationSwitchModeKeypad:
|
|
station.setStationNotificationSwitchMode(types_1.NotificationSwitchMode.KEYPAD, value);
|
|
break;
|
|
case types_1.PropertyName.StationNotificationStartAlarmDelay:
|
|
station.setStationNotificationStartAlarmDelay(value);
|
|
break;
|
|
case types_1.PropertyName.StationTimeFormat:
|
|
station.setStationTimeFormat(value);
|
|
break;
|
|
case types_1.PropertyName.StationSwitchModeWithAccessCode:
|
|
station.setStationSwitchModeWithAccessCode(value);
|
|
break;
|
|
case types_1.PropertyName.StationAutoEndAlarm:
|
|
station.setStationAutoEndAlarm(value);
|
|
break;
|
|
case types_1.PropertyName.StationTurnOffAlarmWithButton:
|
|
station.setStationTurnOffAlarmWithButton(value);
|
|
break;
|
|
case types_1.PropertyName.StationCrossCameraTracking:
|
|
station.setCrossCameraTracking(value);
|
|
break;
|
|
case types_1.PropertyName.StationContinuousTrackingTime:
|
|
station.setContinuousTrackingTime(value);
|
|
break;
|
|
case types_1.PropertyName.StationTrackingAssistance:
|
|
station.setTrackingAssistance(value);
|
|
break;
|
|
case types_1.PropertyName.StationCrossTrackingCameraList:
|
|
station.setCrossTrackingCameraList(value);
|
|
break;
|
|
case types_1.PropertyName.StationCrossTrackingGroupList:
|
|
station.setCrossTrackingGroupList(value);
|
|
break;
|
|
default:
|
|
if (!Object.values(types_1.PropertyName).includes(name))
|
|
throw new error_1.ReadOnlyPropertyError("Property is read only", { context: { station: stationSN, propertyName: name, propertyValue: value } });
|
|
throw new error_2.InvalidPropertyError("Station has no writable property", { context: { station: stationSN, propertyName: name, propertyValue: value } });
|
|
}
|
|
}
|
|
onStartStationLivestream(station, channel, metadata, videostream, audiostream) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
this.emit("station livestream start", station, device, metadata, videostream, audiostream);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station start livestream error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel, metadata: metadata });
|
|
});
|
|
}
|
|
onStopStationLivestream(station, channel) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
this.emit("station livestream stop", station, device);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station stop livestream error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel });
|
|
});
|
|
}
|
|
onErrorStationLivestream(station, channel, origError) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
station.stopLivestream(device);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station livestream error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel, origError: (0, utils_1.getError)(origError) });
|
|
});
|
|
}
|
|
onStartStationRTSPLivestream(station, channel) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
this.emit("station rtsp livestream start", station, device);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station start rtsp livestream error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel });
|
|
});
|
|
}
|
|
onStopStationRTSPLivestream(station, channel) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
this.emit("station rtsp livestream stop", station, device);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station stop rtsp livestream error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel });
|
|
});
|
|
}
|
|
onStationStartDownload(station, channel, metadata, videoStream, audioStream) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
this.emit("station download start", station, device, metadata, videoStream, audioStream);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station start download error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel, metadata: metadata });
|
|
});
|
|
}
|
|
onStationFinishDownload(station, channel) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
this.emit("station download finish", station, device);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station finish download error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel });
|
|
});
|
|
}
|
|
onStationCommandResult(station, result) {
|
|
this.emit("station command result", station, result);
|
|
if (result.return_code === 0) {
|
|
if (result.customData !== undefined && result.customData.onSuccess !== undefined) {
|
|
try {
|
|
result.customData.onSuccess();
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station command result - onSuccess callback error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), result: result });
|
|
}
|
|
}
|
|
this.getStationDevice(station.getSerial(), result.channel).then((device) => {
|
|
if ((result.customData !== undefined && result.customData.property !== undefined && !device.isLockWifiR10() && !device.isLockWifiR20() && !device.isSmartSafe() && !device.isLockWifiT8506() && !device.isLockWifiT8502() && !device.isLockWifiT8510P() && !device.isLockWifiT8520P()) ||
|
|
(result.customData !== undefined && result.customData.property !== undefined && device.isSmartSafe() && result.command_type !== types_2.CommandType.CMD_SMARTSAFE_SETTINGS) ||
|
|
(result.customData !== undefined && result.customData.property !== undefined && (device.isLockWifiT8506() || device.isLockWifiT8502() || device.isLockWifiT8510P() || device.isLockWifiT8520P()) && result.command_type !== types_2.CommandType.CMD_DOORLOCK_SET_PUSH_MODE)) {
|
|
if (device.hasProperty(result.customData.property.name)) {
|
|
const metadata = device.getPropertyMetadata(result.customData.property.name);
|
|
if (typeof result.customData.property.value !== "object" || metadata.type === "object") {
|
|
device.updateProperty(result.customData.property.name, result.customData.property.value);
|
|
}
|
|
}
|
|
else if (station.hasProperty(result.customData.property.name)) {
|
|
const metadata = station.getPropertyMetadata(result.customData.property.name);
|
|
if (typeof result.customData.property.value !== "object" || metadata.type === "object") {
|
|
station.updateProperty(result.customData.property.name, result.customData.property.value);
|
|
}
|
|
}
|
|
}
|
|
else if (result.customData !== undefined && result.customData.command !== undefined && result.customData.command.name === types_1.CommandName.DeviceSnooze) {
|
|
const snoozeTime = result.customData.command.value !== undefined && result.customData.command.value.snooze_time !== undefined ? result.customData.command.value.snooze_time : 0;
|
|
if (snoozeTime > 0) {
|
|
device.updateProperty(types_1.PropertyName.DeviceSnooze, true);
|
|
device.updateProperty(types_1.PropertyName.DeviceSnoozeTime, snoozeTime);
|
|
}
|
|
this.api.refreshAllData().then(() => {
|
|
const snoozeStartTime = device.getPropertyValue(types_1.PropertyName.DeviceSnoozeStartTime);
|
|
const currentTime = Math.trunc(new Date().getTime() / 1000);
|
|
let timeoutMS;
|
|
if (snoozeStartTime !== undefined && snoozeStartTime !== 0) {
|
|
timeoutMS = (snoozeStartTime + snoozeTime - currentTime) * 1000;
|
|
}
|
|
else {
|
|
timeoutMS = snoozeTime * 1000;
|
|
}
|
|
this.deviceSnoozeTimeout[device.getSerial()] = setTimeout(() => {
|
|
device.updateProperty(types_1.PropertyName.DeviceSnooze, false);
|
|
device.updateProperty(types_1.PropertyName.DeviceSnoozeTime, 0);
|
|
device.updateProperty(types_1.PropertyName.DeviceSnoozeStartTime, 0);
|
|
if (device.hasProperty(types_1.PropertyName.DeviceSnoozeHomebase)) {
|
|
device.updateProperty(types_1.PropertyName.DeviceSnoozeHomebase, false);
|
|
}
|
|
if (device.hasProperty(types_1.PropertyName.DeviceSnoozeMotion)) {
|
|
device.updateProperty(types_1.PropertyName.DeviceSnoozeMotion, false);
|
|
}
|
|
if (device.hasProperty(types_1.PropertyName.DeviceSnoozeChime)) {
|
|
device.updateProperty(types_1.PropertyName.DeviceSnoozeChime, false);
|
|
}
|
|
delete this.deviceSnoozeTimeout[device.getSerial()];
|
|
}, timeoutMS);
|
|
}).catch(err => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error("Error during API data refreshing", { error: (0, utils_1.getError)(error) });
|
|
});
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
if (error instanceof error_1.DeviceNotFoundError) {
|
|
if (result.customData !== undefined && result.customData.property !== undefined) {
|
|
station.updateProperty(result.customData.property.name, result.customData.property.value);
|
|
}
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.error(`Station command result error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), result: result });
|
|
}
|
|
});
|
|
if (station.isIntegratedDevice() && result.command_type === types_2.CommandType.CMD_SET_ARMING && station.isConnected() && station.getDeviceType() !== types_1.DeviceType.DOORBELL) {
|
|
station.getCameraInfo();
|
|
}
|
|
}
|
|
else {
|
|
if (result.customData !== undefined && result.customData.onFailure !== undefined) {
|
|
try {
|
|
result.customData.onFailure();
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station command result - onFailure callback error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), result: result });
|
|
}
|
|
}
|
|
}
|
|
if (result.customData !== undefined && result.customData.command !== undefined) {
|
|
const customValue = result.customData.command.value;
|
|
switch (result.customData.command.name) {
|
|
case types_1.CommandName.DeviceAddUser:
|
|
this.getStationDevice(station.getSerial(), result.channel).then((device) => {
|
|
switch (result.return_code) {
|
|
case 0:
|
|
this.emit("user added", device, customValue.username, customValue.schedule);
|
|
break;
|
|
case 4:
|
|
this.emit("user error", device, customValue.username, new error_1.AddUserError("Passcode already used by another user, please choose a different one", { context: { device: device.getSerial(), username: customValue.username, schedule: customValue.schedule } }));
|
|
break;
|
|
default:
|
|
this.emit("user error", device, customValue.username, new error_1.AddUserError("Error creating user", { context: { device: device.getSerial(), username: customValue.username, schedule: customValue.schedule, returnode: result.return_code } }));
|
|
break;
|
|
}
|
|
});
|
|
break;
|
|
case types_1.CommandName.DeviceDeleteUser:
|
|
this.getStationDevice(station.getSerial(), result.channel).then((device) => {
|
|
switch (result.return_code) {
|
|
case 0:
|
|
this.api.deleteUser(device.getSerial(), customValue.shortUserId, device.getStationSerial()).then((result) => {
|
|
if (result) {
|
|
this.emit("user deleted", device, customValue.username);
|
|
}
|
|
else {
|
|
this.emit("user error", device, customValue.username, new error_1.DeleteUserError("Error in deleting user through cloud api call", { context: { device: device.getSerial(), username: customValue.username, shortUserId: customValue.short_user_id } }));
|
|
}
|
|
});
|
|
break;
|
|
default:
|
|
this.emit("user error", device, customValue.username, new error_1.DeleteUserError("Error deleting user", { context: { device: device.getSerial(), username: customValue.username, shortUserId: customValue.short_user_id, returnCode: result.return_code } }));
|
|
break;
|
|
}
|
|
});
|
|
break;
|
|
case types_1.CommandName.DeviceUpdateUserPasscode:
|
|
this.getStationDevice(station.getSerial(), result.channel).then((device) => {
|
|
switch (result.return_code) {
|
|
case 0:
|
|
this.emit("user passcode updated", device, customValue.username);
|
|
break;
|
|
default:
|
|
this.emit("user error", device, customValue.username, new error_1.UpdateUserPasscodeError("Error updating user passcode", { context: { device: device.getSerial(), username: customValue.username, returnCode: result.return_code } }));
|
|
break;
|
|
}
|
|
});
|
|
break;
|
|
case types_1.CommandName.DeviceUpdateUserSchedule:
|
|
this.getStationDevice(station.getSerial(), result.channel).then((device) => {
|
|
switch (result.return_code) {
|
|
case 0:
|
|
this.emit("user schedule updated", device, customValue.username, customValue.schedule);
|
|
break;
|
|
default:
|
|
this.emit("user error", device, customValue.username, new error_1.UpdateUserScheduleError("Error updating user schedule", { context: { device: device.getSerial(), username: customValue.username, schedule: customValue.schedule, returnCode: result.return_code } }));
|
|
break;
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
onStationSecondaryCommandResult(station, result) {
|
|
if (result.return_code === 0) {
|
|
this.getStationDevice(station.getSerial(), result.channel).then((device) => {
|
|
if (result.customData !== undefined && result.customData.property !== undefined) {
|
|
if (device.hasProperty(result.customData.property.name))
|
|
device.updateProperty(result.customData.property.name, result.customData.property.value);
|
|
else if (station.hasProperty(result.customData.property.name)) {
|
|
station.updateProperty(result.customData.property.name, result.customData.property.value);
|
|
}
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
if (error instanceof error_1.DeviceNotFoundError) {
|
|
if (result.customData !== undefined && result.customData.property !== undefined) {
|
|
station.updateProperty(result.customData.property.name, result.customData.property.value);
|
|
}
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.error(`Station secondary command result error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), result: result });
|
|
}
|
|
});
|
|
}
|
|
}
|
|
onStationRtspUrl(station, channel, value) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
this.emit("station rtsp url", station, device, value);
|
|
device.setCustomPropertyValue(types_1.PropertyName.DeviceRTSPStreamUrl, value);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station rtsp url error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel, url: value });
|
|
});
|
|
}
|
|
onStationGuardMode(station, guardMode) {
|
|
this.emit("station guard mode", station, guardMode);
|
|
}
|
|
onStationCurrentMode(station, currentMode) {
|
|
this.emit("station current mode", station, currentMode);
|
|
}
|
|
onStationPropertyChanged(station, name, value, ready) {
|
|
if (ready && !name.startsWith("hidden-")) {
|
|
this.emit("station property changed", station, name, value);
|
|
}
|
|
}
|
|
onStationRawPropertyChanged(station, type, value) {
|
|
this.emit("station raw property changed", station, type, value);
|
|
}
|
|
onStationAlarmEvent(station, alarmEvent) {
|
|
this.emit("station alarm event", station, alarmEvent);
|
|
}
|
|
onStationAlarmDelayEvent(station, alarmDelayEvent, alarmDelay) {
|
|
this.emit("station alarm delay event", station, alarmDelayEvent, alarmDelay);
|
|
}
|
|
onStationArmDelayEvent(station, armDelay) {
|
|
this.emit("station alarm arm delay event", station, armDelay);
|
|
}
|
|
onStationAlarmArmedEvent(station) {
|
|
this.emit("station alarm armed", station);
|
|
}
|
|
onDevicePropertyChanged(device, name, value, ready) {
|
|
try {
|
|
if (ready && !name.startsWith("hidden-")) {
|
|
this.emit("device property changed", device, name, value);
|
|
}
|
|
if (name === types_1.PropertyName.DeviceRTSPStream && value === true && (device.getPropertyValue(types_1.PropertyName.DeviceRTSPStreamUrl) === undefined || (device.getPropertyValue(types_1.PropertyName.DeviceRTSPStreamUrl) !== undefined && device.getPropertyValue(types_1.PropertyName.DeviceRTSPStreamUrl) === ""))) {
|
|
this.getStation(device.getStationSerial()).then((station) => {
|
|
station.setRTSPStream(device, true);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Device property changed error - station enable rtsp`, { error: (0, utils_1.getError)(error), deviceSN: device.getSerial(), stationSN: device.getStationSerial(), propertyName: name, propertyValue: value, ready: ready });
|
|
});
|
|
}
|
|
else if (name === types_1.PropertyName.DeviceRTSPStream && value === false) {
|
|
device.setCustomPropertyValue(types_1.PropertyName.DeviceRTSPStreamUrl, "");
|
|
}
|
|
else if (name === types_1.PropertyName.DevicePictureUrl && value !== "") {
|
|
if (!(0, utils_1.isValidUrl)(value)) {
|
|
this.getStation(device.getStationSerial()).then((station) => {
|
|
if (station.hasCommand(types_1.CommandName.StationDownloadImage)) {
|
|
station.downloadImage(value);
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Device property changed error - station download image`, { error: (0, utils_1.getError)(error), deviceSN: device.getSerial(), stationSN: device.getStationSerial(), propertyName: name, propertyValue: value, ready: ready });
|
|
});
|
|
}
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Device property changed error`, { error: (0, utils_1.getError)(error), deviceSN: device.getSerial(), stationSN: device.getStationSerial(), propertyName: name, propertyValue: value, ready: ready });
|
|
}
|
|
}
|
|
onDeviceRawPropertyChanged(device, type, value) {
|
|
this.emit("device raw property changed", device, type, value);
|
|
}
|
|
onDeviceCryingDetected(device, state) {
|
|
this.emit("device crying detected", device, state);
|
|
}
|
|
onDeviceSoundDetected(device, state) {
|
|
this.emit("device sound detected", device, state);
|
|
}
|
|
onDevicePetDetected(device, state) {
|
|
this.emit("device pet detected", device, state);
|
|
}
|
|
onDeviceVehicleDetected(device, state) {
|
|
this.emit("device vehicle detected", device, state);
|
|
}
|
|
onDeviceMotionDetected(device, state) {
|
|
this.emit("device motion detected", device, state);
|
|
}
|
|
onDevicePersonDetected(device, state, person) {
|
|
this.emit("device person detected", device, state, person);
|
|
}
|
|
onDeviceRings(device, state) {
|
|
this.emit("device rings", device, state);
|
|
}
|
|
onDeviceLocked(device, state) {
|
|
this.emit("device locked", device, state);
|
|
}
|
|
onDeviceOpen(device, state) {
|
|
this.emit("device open", device, state);
|
|
}
|
|
onDevicePackageDelivered(device, state) {
|
|
this.emit("device package delivered", device, state);
|
|
}
|
|
onDevicePackageStranded(device, state) {
|
|
this.emit("device package stranded", device, state);
|
|
}
|
|
onDevicePackageTaken(device, state) {
|
|
this.emit("device package taken", device, state);
|
|
}
|
|
onDeviceSomeoneLoitering(device, state) {
|
|
this.emit("device someone loitering", device, state);
|
|
}
|
|
onDeviceRadarMotionDetected(device, state) {
|
|
this.emit("device radar motion detected", device, state);
|
|
}
|
|
onDevice911Alarm(device, state, detail) {
|
|
this.emit("device 911 alarm", device, state, detail);
|
|
}
|
|
onDeviceShakeAlarm(device, state, detail) {
|
|
this.emit("device shake alarm", device, state, detail);
|
|
}
|
|
onDeviceWrongTryProtectAlarm(device, state) {
|
|
this.emit("device wrong try-protect alarm", device, state);
|
|
}
|
|
onDeviceLongTimeNotClose(device, state) {
|
|
this.emit("device long time not close", device, state);
|
|
}
|
|
onDeviceLowBattery(device, state) {
|
|
this.emit("device low battery", device, state);
|
|
}
|
|
onDeviceJammed(device, state) {
|
|
this.emit("device jammed", device, state);
|
|
}
|
|
onDeviceStrangerPersonDetected(device, state) {
|
|
this.emit("device stranger person detected", device, state);
|
|
}
|
|
onDeviceDogDetected(device, state) {
|
|
this.emit("device dog detected", device, state);
|
|
}
|
|
onDeviceDogLickDetected(device, state) {
|
|
this.emit("device dog lick detected", device, state);
|
|
}
|
|
onDeviceDogPoopDetected(device, state) {
|
|
this.emit("device dog poop detected", device, state);
|
|
}
|
|
onDeviceReady(device) {
|
|
try {
|
|
if (device.getPropertyValue(types_1.PropertyName.DeviceRTSPStream) !== undefined && device.getPropertyValue(types_1.PropertyName.DeviceRTSPStream) === true) {
|
|
this.getStation(device.getStationSerial()).then((station) => {
|
|
station.setRTSPStream(device, true);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Device ready error - station enable rtsp`, { error: (0, utils_1.getError)(error), deviceSN: device.getSerial(), stationSN: device.getStationSerial() });
|
|
});
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Device ready error`, { error: (0, utils_1.getError)(error), deviceSN: device.getSerial(), stationSN: device.getStationSerial() });
|
|
}
|
|
}
|
|
onStationRuntimeState(station, channel, batteryLevel, temperature) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
if (device.hasProperty(types_1.PropertyName.DeviceBattery)) {
|
|
const metadataBattery = device.getPropertyMetadata(types_1.PropertyName.DeviceBattery);
|
|
device.updateRawProperty(metadataBattery.key, batteryLevel.toString(), "p2p");
|
|
}
|
|
if (device.hasProperty(types_1.PropertyName.DeviceBatteryTemp)) {
|
|
const metadataBatteryTemperature = device.getPropertyMetadata(types_1.PropertyName.DeviceBatteryTemp);
|
|
device.updateRawProperty(metadataBatteryTemperature.key, temperature.toString(), "p2p");
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station runtime state error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel, batteryLevel: batteryLevel, temperature: temperature });
|
|
});
|
|
}
|
|
onStationChargingState(station, channel, chargeType, batteryLevel) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
if (device.hasProperty(types_1.PropertyName.DeviceBattery)) {
|
|
const metadataBattery = device.getPropertyMetadata(types_1.PropertyName.DeviceBattery);
|
|
if ((0, utils_3.isCharging)(chargeType) && batteryLevel > 0)
|
|
device.updateRawProperty(metadataBattery.key, batteryLevel.toString(), "p2p");
|
|
}
|
|
if (device.hasProperty(types_1.PropertyName.DeviceChargingStatus)) {
|
|
const metadataChargingStatus = device.getPropertyMetadata(types_1.PropertyName.DeviceChargingStatus);
|
|
device.updateRawProperty(metadataChargingStatus.key, chargeType.toString(), "p2p");
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station charging state error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel, chargeType: chargeType, charging: (0, utils_3.isCharging)(chargeType), batteryLevel: batteryLevel });
|
|
});
|
|
}
|
|
onStationWifiRssi(station, channel, rssi) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
if (device.hasProperty(types_1.PropertyName.DeviceWifiRSSI)) {
|
|
const metadataWifiRssi = device.getPropertyMetadata(types_1.PropertyName.DeviceWifiRSSI);
|
|
device.updateRawProperty(metadataWifiRssi.key, rssi.toString(), "p2p");
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station wifi rssi error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel, rssi: rssi });
|
|
});
|
|
}
|
|
onCaptchaRequest(id, captcha) {
|
|
this.emit("captcha request", id, captcha);
|
|
}
|
|
onFloodlightManualSwitch(station, channel, enabled) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
if (device.hasProperty(types_1.PropertyName.DeviceLight)) {
|
|
const metadataLight = device.getPropertyMetadata(types_1.PropertyName.DeviceLight);
|
|
device.updateRawProperty(metadataLight.key, enabled === true ? "1" : "0", "p2p");
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station floodlight manual switch error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel, enabled: enabled });
|
|
});
|
|
}
|
|
onAuthTokenInvalidated() {
|
|
this.persistentData.cloud_token = undefined;
|
|
this.persistentData.cloud_token_expiration = undefined;
|
|
this.writePersistentData();
|
|
}
|
|
onTfaRequest() {
|
|
this.emit("tfa request");
|
|
}
|
|
onStationTalkbackStart(station, channel, talkbackStream) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
this.emit("station talkback start", station, device, talkbackStream);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station talkback start error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel });
|
|
});
|
|
}
|
|
onStationTalkbackStop(station, channel) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
this.emit("station talkback stop", station, device);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station talkback stop error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel });
|
|
});
|
|
}
|
|
onStationTalkbackError(station, channel, origError) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
station.stopTalkback(device);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station talkback error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel, origError: (0, utils_1.getError)(origError) });
|
|
});
|
|
}
|
|
async startStationTalkback(deviceSN) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
if (!device.hasCommand(types_1.CommandName.DeviceStartTalkback))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStartTalkback } });
|
|
if (station.isLiveStreaming(device)) {
|
|
if (!station.isTalkbackOngoing(device)) {
|
|
station.startTalkback(device);
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.warn(`The station talkback for the device ${deviceSN} cannot be started, because it is ongoing!`);
|
|
}
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.warn(`The station talkback for the device ${deviceSN} cannot be started, because it isn't live streaming!`);
|
|
}
|
|
}
|
|
async stopStationTalkback(deviceSN) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
if (!device.hasCommand(types_1.CommandName.DeviceStopTalkback))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceStopTalkback } });
|
|
if (station.isLiveStreaming(device)) {
|
|
if (station.isTalkbackOngoing(device)) {
|
|
station.stopTalkback(device);
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.warn(`The station talkback for the device ${deviceSN} cannot be stopped, because it isn't ongoing!`);
|
|
}
|
|
}
|
|
else {
|
|
logging_1.rootMainLogger.warn(`The station talkback for the device ${deviceSN} cannot be stopped, because it isn't live streaming!`);
|
|
}
|
|
}
|
|
onStationDeviceShakeAlarm(deviceSN, event) {
|
|
this.getDevice(deviceSN).then((device) => {
|
|
if (device.isSmartSafe())
|
|
device.shakeEvent(event, this.config.eventDurationSeconds);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`onStationDeviceShakeAlarm error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN, event: types_2.SmartSafeShakeAlarmEvent[event] });
|
|
});
|
|
}
|
|
onStationDevice911Alarm(deviceSN, event) {
|
|
this.getDevice(deviceSN).then((device) => {
|
|
if (device.isSmartSafe())
|
|
device.alarm911Event(event, this.config.eventDurationSeconds);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`onStationDevice911Alarm error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN, event: types_2.SmartSafeAlarm911Event[event] });
|
|
});
|
|
}
|
|
onStationDeviceJammed(deviceSN) {
|
|
this.getDevice(deviceSN).then((device) => {
|
|
if (device.isSmartSafe())
|
|
device.jammedEvent(this.config.eventDurationSeconds);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`onStationDeviceJammed error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN });
|
|
});
|
|
}
|
|
onStationDeviceLowBattery(deviceSN) {
|
|
this.getDevice(deviceSN).then((device) => {
|
|
if (device.isSmartSafe())
|
|
device.lowBatteryEvent(this.config.eventDurationSeconds);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`onStationDeviceLowBattery error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN });
|
|
});
|
|
}
|
|
onStationDeviceWrongTryProtectAlarm(deviceSN) {
|
|
this.getDevice(deviceSN).then((device) => {
|
|
if (device.isSmartSafe())
|
|
device.wrongTryProtectAlarmEvent(this.config.eventDurationSeconds);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`onStationDeviceWrongTryProtectAlarm error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN });
|
|
});
|
|
}
|
|
async addUser(deviceSN, username, passcode, schedule) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
try {
|
|
if (!device.hasCommand(types_1.CommandName.DeviceAddUser))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceAddUser, username: username, passcode: "[redacted]", schedule: schedule } });
|
|
const addUserResponse = await this.api.addUser(deviceSN, username, device.getStationSerial());
|
|
if (addUserResponse !== null) {
|
|
station.addUser(device, username, addUserResponse.short_user_id, passcode, schedule);
|
|
}
|
|
else {
|
|
this.emit("user error", device, username, new error_1.AddUserError("Error on creating user through cloud api call", { context: { deivce: deviceSN, username: username, passcode: "[redacted]", schedule: schedule } }));
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`addUser error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN, username: username, schedule: schedule });
|
|
this.emit("user error", device, username, new error_1.AddUserError("Generic error", { cause: error, context: { device: deviceSN, username: username, passcode: "[redacted]", schedule: schedule } }));
|
|
}
|
|
}
|
|
async deleteUser(deviceSN, username) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
if (!device.hasCommand(types_1.CommandName.DeviceDeleteUser))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceDeleteUser, username: username } });
|
|
try {
|
|
const users = await this.api.getUsers(deviceSN, device.getStationSerial());
|
|
if (users !== null) {
|
|
let found = false;
|
|
for (const user of users) {
|
|
if (user.user_name === username) {
|
|
station.deleteUser(device, user.user_name, user.short_user_id);
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
this.emit("user error", device, username, new error_1.DeleteUserError("User not found", { context: { device: deviceSN, username: username } }));
|
|
}
|
|
}
|
|
else {
|
|
this.emit("user error", device, username, new error_1.DeleteUserError("Error on getting user list through cloud api call", { context: { device: deviceSN, username: username } }));
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`deleteUser error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN, username: username });
|
|
this.emit("user error", device, username, new error_1.DeleteUserError("Generic error", { cause: error, context: { device: deviceSN, username: username } }));
|
|
}
|
|
}
|
|
async updateUser(deviceSN, username, newUsername) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
if (!device.hasCommand(types_1.CommandName.DeviceUpdateUsername))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceUpdateUsername, usernmae: username, newUsername: newUsername } });
|
|
try {
|
|
const users = await this.api.getUsers(deviceSN, device.getStationSerial());
|
|
if (users !== null) {
|
|
let found = false;
|
|
for (const user of users) {
|
|
if (user.user_name === username) {
|
|
if ((device.isLockWifiT8506() || device.isLockWifiT8502() || device.isLockWifiT8510P() || device.isLockWifiT8520P()) && user.password_list.length > 0) {
|
|
for (const entry of user.password_list) {
|
|
if (entry.password_type === types_1.UserPasswordType.PIN) {
|
|
let schedule = entry.schedule;
|
|
if (schedule !== undefined && typeof schedule == "string") {
|
|
schedule = JSON.parse(schedule);
|
|
}
|
|
if (schedule !== undefined && schedule.endDay !== undefined && schedule.endTime !== undefined && schedule.startDay !== undefined && schedule.startTime !== undefined && schedule.week !== undefined) {
|
|
station.updateUserSchedule(device, newUsername, user.short_user_id, (0, utils_2.hexStringScheduleToSchedule)(schedule.startDay, schedule.startTime, schedule.endDay, schedule.endTime, schedule.week));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (device.isLockWifiR10() || device.isLockWifiR20()) {
|
|
for (const entry of user.password_list) {
|
|
if (entry.password_type === types_1.UserPasswordType.PIN) {
|
|
station.updateUsername(device, newUsername, entry.password_id);
|
|
}
|
|
}
|
|
}
|
|
const result = await this.api.updateUser(deviceSN, device.getStationSerial(), user.short_user_id, newUsername);
|
|
if (result) {
|
|
this.emit("user username updated", device, username);
|
|
}
|
|
else {
|
|
this.emit("user error", device, username, new error_1.UpdateUserUsernameError("Error in changing username through cloud api call", { context: { device: deviceSN, username: username, newUsername: newUsername } }));
|
|
}
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
this.emit("user error", device, username, new error_1.UpdateUserUsernameError("User not found", { context: { device: deviceSN, username: username, newUsername: newUsername } }));
|
|
}
|
|
}
|
|
else {
|
|
this.emit("user error", device, username, new error_1.UpdateUserUsernameError("Error on getting user list through cloud api call", { context: { device: deviceSN, username: username, newUsername: newUsername } }));
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`updateUser error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN, username: username, newUsername: newUsername });
|
|
this.emit("user error", device, username, new error_1.UpdateUserUsernameError("Generic error", { cause: error, context: { device: deviceSN, username: username, newUsername: newUsername } }));
|
|
}
|
|
}
|
|
async updateUserPasscode(deviceSN, username, passcode) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
if (!device.hasCommand(types_1.CommandName.DeviceUpdateUserPasscode))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceUpdateUserPasscode, username: username, passcode: "[redacted]" } });
|
|
try {
|
|
const users = await this.api.getUsers(deviceSN, device.getStationSerial());
|
|
if (users !== null) {
|
|
let found = false;
|
|
for (const user of users) {
|
|
if (user.user_name === username) {
|
|
for (const entry of user.password_list) {
|
|
if (entry.password_type === types_1.UserPasswordType.PIN) {
|
|
station.updateUserPasscode(device, user.user_name, entry.password_id, passcode);
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!found) {
|
|
this.emit("user error", device, username, new error_1.UpdateUserPasscodeError("User not found", { context: { device: deviceSN, username: username, passcode: "[redacted]" } }));
|
|
}
|
|
}
|
|
else {
|
|
this.emit("user error", device, username, new error_1.UpdateUserPasscodeError("Error on getting user list through cloud api call", { context: { device: deviceSN, username: username, passcode: "[redacted]" } }));
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`updateUserPasscode error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN, username: username });
|
|
this.emit("user error", device, username, new error_1.UpdateUserPasscodeError("Generic error", { cause: error, context: { device: deviceSN, username: username, passcode: "[redacted]" } }));
|
|
}
|
|
}
|
|
async updateUserSchedule(deviceSN, username, schedule) {
|
|
const device = await this.getDevice(deviceSN);
|
|
const station = await this.getStation(device.getStationSerial());
|
|
if (!device.hasCommand(types_1.CommandName.DeviceUpdateUserSchedule))
|
|
throw new error_1.NotSupportedError("This functionality is not implemented or supported by this device", { context: { device: deviceSN, commandName: types_1.CommandName.DeviceUpdateUserSchedule, usernmae: username, schedule: schedule } });
|
|
try {
|
|
const users = await this.api.getUsers(deviceSN, device.getStationSerial());
|
|
if (users !== null) {
|
|
let found = false;
|
|
for (const user of users) {
|
|
if (user.user_name === username) {
|
|
station.updateUserSchedule(device, user.user_name, user.short_user_id, schedule);
|
|
found = true;
|
|
}
|
|
}
|
|
if (!found) {
|
|
this.emit("user error", device, username, new error_1.UpdateUserScheduleError("User not found", { context: { device: deviceSN, username: username, schedule: schedule } }));
|
|
}
|
|
}
|
|
else {
|
|
this.emit("user error", device, username, new error_1.UpdateUserScheduleError("Error on getting user list through cloud api call", { context: { device: deviceSN, username: username, schedule: schedule } }));
|
|
}
|
|
}
|
|
catch (err) {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`updateUserSchedule error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN, username: username, schedule: schedule });
|
|
this.emit("user error", device, username, new error_1.UpdateUserScheduleError("Generic error", { cause: error, context: { device: deviceSN, username: username, schedule: schedule } }));
|
|
}
|
|
}
|
|
onStationDevicePinVerified(deviceSN, successfull) {
|
|
this.getDevice(deviceSN).then((device) => {
|
|
this.emit("device pin verified", device, successfull);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`onStationDevicePinVerified error`, { error: (0, utils_1.getError)(error), deviceSN: deviceSN, successfull: successfull });
|
|
});
|
|
}
|
|
onStationSdInfoEx(station, sdStatus, sdCapacity, sdCapacityAvailable) {
|
|
if (station.hasProperty(types_1.PropertyName.StationSdStatus)) {
|
|
station.updateProperty(types_1.PropertyName.StationSdStatus, sdStatus);
|
|
}
|
|
if (station.hasProperty(types_1.PropertyName.StationSdCapacity)) {
|
|
station.updateProperty(types_1.PropertyName.StationSdCapacity, sdCapacity);
|
|
}
|
|
if (station.hasProperty(types_1.PropertyName.StationSdCapacityAvailable)) {
|
|
station.updateProperty(types_1.PropertyName.StationSdCapacityAvailable, sdCapacityAvailable);
|
|
}
|
|
}
|
|
_emitStationImageDownload(station, file, picture) {
|
|
this.emit("station image download", station, file, picture);
|
|
this.getDevicesFromStation(station.getSerial()).then((devices) => {
|
|
for (const device of devices) {
|
|
if (device.getPropertyValue(types_1.PropertyName.DevicePictureUrl) === file) {
|
|
logging_1.rootMainLogger.debug(`onStationImageDownload - Set picture for device ${device.getSerial()} file: ${file} picture_ext: ${picture.type.ext} picture_mime: ${picture.type.mime}`);
|
|
device.updateProperty(types_1.PropertyName.DevicePicture, picture);
|
|
break;
|
|
}
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`onStationImageDownload - Set picture error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), file: file });
|
|
});
|
|
}
|
|
onStationImageDownload(station, file, image) {
|
|
import("image-type").then(({ default: imageType }) => {
|
|
imageType(image).then((type) => {
|
|
const picture = {
|
|
data: image,
|
|
type: type !== null && type !== undefined ? type : { ext: "unknown", mime: "application/octet-stream" }
|
|
};
|
|
this._emitStationImageDownload(station, file, picture);
|
|
}).catch(() => {
|
|
this._emitStationImageDownload(station, file, {
|
|
data: image,
|
|
type: { ext: "unknown", mime: "application/octet-stream" }
|
|
});
|
|
});
|
|
}).catch(() => {
|
|
this._emitStationImageDownload(station, file, {
|
|
data: image,
|
|
type: { ext: "unknown", mime: "application/octet-stream" }
|
|
});
|
|
});
|
|
}
|
|
onStationDatabaseQueryLatest(station, returnCode, data) {
|
|
if (returnCode === types_2.DatabaseReturnCode.SUCCESSFUL) {
|
|
for (const element of data) {
|
|
if ((element.device_sn !== "" && !station.isStation()) || (station.isStation() && element.device_sn !== station.getSerial())) {
|
|
this.getDevice(element.device_sn).then((device) => {
|
|
const raw = device.getRawDevice();
|
|
if ("crop_local_path" in element) {
|
|
raw.cover_path = element.crop_local_path;
|
|
}
|
|
else if ("crop_cloud_path" in element) {
|
|
raw.cover_path = element.crop_cloud_path;
|
|
}
|
|
device.update(raw);
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
if (!(error instanceof error_1.DeviceNotFoundError)) {
|
|
logging_1.rootMainLogger.error("onStationDatabaseQueryLatest Error", { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), returnCode: returnCode });
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
this.emit("station database query latest", station, returnCode, data);
|
|
}
|
|
onStationDatabaseQueryLocal(station, returnCode, data) {
|
|
this.emit("station database query local", station, returnCode, data);
|
|
}
|
|
onStationDatabaseCountByDate(station, returnCode, data) {
|
|
this.emit("station database count by date", station, returnCode, data);
|
|
}
|
|
onStationDatabaseDelete(station, returnCode, failedIds) {
|
|
this.emit("station database delete", station, returnCode, failedIds);
|
|
}
|
|
onStationSensorStatus(station, channel, status) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
if (device.hasProperty(types_1.PropertyName.DeviceSensorOpen)) {
|
|
const metadataSensorOpen = device.getPropertyMetadata(types_1.PropertyName.DeviceSensorOpen);
|
|
device.updateRawProperty(metadataSensorOpen.key, status.toString(), "p2p");
|
|
}
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station sensor status error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel });
|
|
});
|
|
}
|
|
onStationGarageDoorStatus(station, channel, doorId, status) {
|
|
this.getStationDevice(station.getSerial(), channel).then((device) => {
|
|
device.updateRawProperty(types_2.CommandType.CMD_CAMERA_GARAGE_DOOR_STATUS, status.toString(), "p2p");
|
|
}).catch((err) => {
|
|
const error = (0, error_1.ensureError)(err);
|
|
logging_1.rootMainLogger.error(`Station garage door status error`, { error: (0, utils_1.getError)(error), stationSN: station.getSerial(), channel: channel });
|
|
});
|
|
}
|
|
onStorageInfoHb3(station, channel, storageInfo) {
|
|
if (station.hasProperty(types_1.PropertyName.StationStorageInfoEmmc)) {
|
|
station.updateProperty(types_1.PropertyName.StationStorageInfoEmmc, storageInfo.emmc_info);
|
|
}
|
|
if (station.hasProperty(types_1.PropertyName.StationStorageInfoHdd)) {
|
|
station.updateProperty(types_1.PropertyName.StationStorageInfoHdd, storageInfo.hdd_info);
|
|
}
|
|
}
|
|
onDeviceTampering(device, state) {
|
|
this.emit("device tampering", device, state);
|
|
}
|
|
onDeviceLowTemperature(device, state) {
|
|
this.emit("device low temperature", device, state);
|
|
}
|
|
onDeviceHighTemperature(device, state) {
|
|
this.emit("device high temperature", device, state);
|
|
}
|
|
onDevicePinIncorrect(device, state) {
|
|
this.emit("device pin incorrect", device, state);
|
|
}
|
|
onDeviceLidStuck(device, state) {
|
|
this.emit("device lid stuck", device, state);
|
|
}
|
|
onDeviceBatteryFullyCharged(device, state) {
|
|
this.emit("device battery fully charged", device, state);
|
|
}
|
|
}
|
|
exports.EufySecurity = EufySecurity;
|
|
//# sourceMappingURL=eufysecurity.js.map
|